summaryrefslogtreecommitdiff
path: root/libs/cassowary
diff options
context:
space:
mode:
Diffstat (limited to 'libs/cassowary')
-rw-r--r--libs/cassowary/.cvsignore15
-rw-r--r--libs/cassowary/ANNOUNCE37
-rw-r--r--libs/cassowary/AUTHORS12
-rw-r--r--libs/cassowary/COPYING340
-rw-r--r--libs/cassowary/COPYING.LGPL444
-rw-r--r--libs/cassowary/ChangeLog2002
-rw-r--r--libs/cassowary/ClAbstractVariable.cc23
-rw-r--r--libs/cassowary/ClBug0.cc102
-rw-r--r--libs/cassowary/ClBug1.cc21
-rw-r--r--libs/cassowary/ClBug2.cc130
-rw-r--r--libs/cassowary/ClConstraint.cc32
-rw-r--r--libs/cassowary/ClDummyVariable.cc12
-rw-r--r--libs/cassowary/ClFDBinaryOneWayConstraint.cc140
-rw-r--r--libs/cassowary/ClFDConnectorVariable.cc29
-rw-r--r--libs/cassowary/ClFDSolver.cc364
-rw-r--r--libs/cassowary/ClFDVariable.cc27
-rw-r--r--libs/cassowary/ClFloatVariable.cc25
-rw-r--r--libs/cassowary/ClLinearExpression.cc473
-rw-r--r--libs/cassowary/ClReader.l87
-rw-r--r--libs/cassowary/ClReader.y154
-rw-r--r--libs/cassowary/ClSimplexSolver.cc1633
-rw-r--r--libs/cassowary/ClSlackVariable.cc12
-rw-r--r--libs/cassowary/ClSolver.cc59
-rw-r--r--libs/cassowary/ClStrength.cc52
-rw-r--r--libs/cassowary/ClSymbolicWeight.cc149
-rw-r--r--libs/cassowary/ClTableau.cc297
-rw-r--r--libs/cassowary/ClTests.cc884
-rw-r--r--libs/cassowary/ClVariable.cc21
-rw-r--r--libs/cassowary/IMPORTANT26
-rw-r--r--libs/cassowary/INSTALL182
-rw-r--r--libs/cassowary/LICENSE18
-rw-r--r--libs/cassowary/Makefile.am32
-rw-r--r--libs/cassowary/NEWS229
-rw-r--r--libs/cassowary/README241
-rw-r--r--libs/cassowary/THANKS30
-rw-r--r--libs/cassowary/autogen.sh4
-rwxr-xr-xlibs/cassowary/cassowary-config102
-rwxr-xr-xlibs/cassowary/cassowary-config.in102
-rw-r--r--libs/cassowary/cassowary-nofd.spec284
-rw-r--r--libs/cassowary/cassowary-nofd.spec2.in84
-rw-r--r--libs/cassowary/cassowary.spec78
-rw-r--r--libs/cassowary/cassowary.spec.in78
-rw-r--r--libs/cassowary/cassowary/.cvsignore2
-rw-r--r--libs/cassowary/cassowary/Cassowary.h40
-rw-r--r--libs/cassowary/cassowary/Cl.h49
-rw-r--r--libs/cassowary/cassowary/ClAbstractVariable.h161
-rw-r--r--libs/cassowary/cassowary/ClConstraint.h198
-rw-r--r--libs/cassowary/cassowary/ClConstraintHash.h39
-rw-r--r--libs/cassowary/cassowary/ClDummyVariable.h88
-rw-r--r--libs/cassowary/cassowary/ClEditConstraint.h45
-rw-r--r--libs/cassowary/cassowary/ClEditOrStayConstraint.h51
-rw-r--r--libs/cassowary/cassowary/ClErrors.h179
-rw-r--r--libs/cassowary/cassowary/ClFDBinaryOneWayConstraint.h94
-rw-r--r--libs/cassowary/cassowary/ClFDConnectorVariable.h89
-rw-r--r--libs/cassowary/cassowary/ClFDConstraint.h40
-rw-r--r--libs/cassowary/cassowary/ClFDSolver.h120
-rw-r--r--libs/cassowary/cassowary/ClFDVariable.h126
-rw-r--r--libs/cassowary/cassowary/ClFloatVariable.h119
-rw-r--r--libs/cassowary/cassowary/ClLinearConstraint.h61
-rw-r--r--libs/cassowary/cassowary/ClLinearEquation.h74
-rw-r--r--libs/cassowary/cassowary/ClLinearExpression.h298
-rw-r--r--libs/cassowary/cassowary/ClLinearExpression_fwd.h26
-rw-r--r--libs/cassowary/cassowary/ClLinearInequality.h167
-rw-r--r--libs/cassowary/cassowary/ClObjectiveVariable.h63
-rw-r--r--libs/cassowary/cassowary/ClPoint.h74
-rw-r--r--libs/cassowary/cassowary/ClReader.h117
-rw-r--r--libs/cassowary/cassowary/ClSimplexSolver.h588
-rw-r--r--libs/cassowary/cassowary/ClSlackVariable.h75
-rw-r--r--libs/cassowary/cassowary/ClSolver.h167
-rw-r--r--libs/cassowary/cassowary/ClStayConstraint.h43
-rw-r--r--libs/cassowary/cassowary/ClStrength.h91
-rw-r--r--libs/cassowary/cassowary/ClSymbolicWeight.h197
-rw-r--r--libs/cassowary/cassowary/ClTableau.h230
-rw-r--r--libs/cassowary/cassowary/ClTypedefs.h48
-rw-r--r--libs/cassowary/cassowary/ClVariable.h166
-rw-r--r--libs/cassowary/cassowary/Makefile.am36
-rw-r--r--libs/cassowary/cassowary/cl_auto_ptr.h69
-rw-r--r--libs/cassowary/cassowary/config-inline.h1
-rw-r--r--libs/cassowary/cassowary/debug.h48
-rw-r--r--libs/cassowary/cassowary/timer.h176
-rw-r--r--libs/cassowary/configure.ac64
81 files changed, 13185 insertions, 0 deletions
diff --git a/libs/cassowary/.cvsignore b/libs/cassowary/.cvsignore
new file mode 100644
index 0000000000..7ac7ae08ae
--- /dev/null
+++ b/libs/cassowary/.cvsignore
@@ -0,0 +1,15 @@
+.deps
+ClReader-lex.cc
+ClReader.cc
+ClReader.hh
+ClReader.cc.h
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+config.h
+config.h.in
+config.log
+config.status
+configure
+stamp-h1
diff --git a/libs/cassowary/ANNOUNCE b/libs/cassowary/ANNOUNCE
new file mode 100644
index 0000000000..e0137fa643
--- /dev/null
+++ b/libs/cassowary/ANNOUNCE
@@ -0,0 +1,37 @@
+Announcing the release of a free (for research use) constraint solver:
+
+Cassowary Constraint Solver for Smalltalk, C++, and Java
+Version 0.60
+
+Web Page: http://www.cs.washington.edu/research/constraints/cassowary
+Distribution: ftp://ftp.cs.washington.edu:/pub/constraints/code/cassowary/
+Contact: cassowary@cs.washington.edu
+
+Greg J. Badros <gjb@cs.washington.edu> and
+Alan Borning <borning@cs.washington.edu>
+University of Washington
+Computer Science and Engineering
+15-December-1999
+
+with Constraint Drawing Applet (CDA) by Michael Noth <noth@cs.washington.edu>
+
+Cassowary is an incremental constraint solving toolkit that efficiently
+solves systems of linear equalities and inequalities. Constraints may
+be either requirements or preferences. Client code specifies the
+constraints to be maintained, and the solver updates the constrained
+variables to have values that satisfy the constraints.
+
+A technical report is included in the distribution that describes the
+algorithm, interface, and implementation of the Cassowary solver.
+Additionally, the distribution contains toy sample applications written
+in Smalltalk, C++, Java, and Python, and a more complex example Java
+applet, the "Constraint Drawing Application".
+
+More information is available on our web page:
+
+http://www.cs.washington.edu/research/constraints/cassowary
+
+See README for more details on getting started using these packages.
+See NEWS for a history of user-visible changes.
+See LICENSE for legalese regarding use of this distribution.
+
diff --git a/libs/cassowary/AUTHORS b/libs/cassowary/AUTHORS
new file mode 100644
index 0000000000..51d8592e6f
--- /dev/null
+++ b/libs/cassowary/AUTHORS
@@ -0,0 +1,12 @@
+Cassowary Constraint Solving Toolkit was
+Implemented by:
+
+Greg J. Badros <gjb@cs.washington.edu> and
+Alan Borning <borning@cs.washington.edu>
+University of Washington
+Computer Science and Engineering
+Seattle, WA 98195-2350
+
+with Constraint Drawing Applet (CDA) by Michael Noth <noth@cs.washington.edu>
+
+Please send bug reports to cassowary@cs.washington.edu
diff --git a/libs/cassowary/COPYING b/libs/cassowary/COPYING
new file mode 100644
index 0000000000..d60c31a97a
--- /dev/null
+++ b/libs/cassowary/COPYING
@@ -0,0 +1,340 @@
+ 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.
diff --git a/libs/cassowary/COPYING.LGPL b/libs/cassowary/COPYING.LGPL
new file mode 100644
index 0000000000..5f66256a83
--- /dev/null
+++ b/libs/cassowary/COPYING.LGPL
@@ -0,0 +1,444 @@
+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.
+
+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
diff --git a/libs/cassowary/ChangeLog b/libs/cassowary/ChangeLog
new file mode 100644
index 0000000000..be31e0e5a9
--- /dev/null
+++ b/libs/cassowary/ChangeLog
@@ -0,0 +1,2002 @@
+Fri Mar 18 15:41:00 2005 Taybin Rutkin <taybin@earthlink.net>
+ * Removed ClSet.h, ClMap.h.
+ * ClReader.l includes ClReader.cc.h instead of ClReader.hh. The
+ difference between yacc and bison.
+ * Various changes to fix compliation.
+
+Wed Jan 29 21:36:15 2003 Taybin Rutkin <trutkin@physics.clarku.edu>
+ * Updated to work with g++ 3.x compilers.
+ * More direct use of STL.
+ * Removed C wrappers
+
+Sun Mar 12 13:40:44 2000 Greg J. Badros <gjb@cs.washington.edu>
+
+ * guile/cassowary_scm.cc: Give docstrings as arguments
+
+ * guile/cl-snarf.h: Added docstring as an argument to CL_PROC to
+ be like the revised Scwm documentation extraction system.
+
+Sat Feb 12 20:34:55 2000 Greg J. Badros <gjb@cs.washington.edu>
+
+ * Makefile.am: Added GTL.h.patch to EXTRA_DIST
+
+Sat Feb 12 20:31:47 2000 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/ClSimplexSolver.cc, c++/ClSimplexSolver.h: Drop
+ ExternalResetStayConstants, make ResetStayConstants() public.
+ Test _fResetStayConstantsAutomatically before doing so in
+ Resolve(). Use _fAutosolve instead of _fOptimizeAutomatically.
+ Drop DisplayObjective (wasn't defined anyway). Drop field
+ _fOptimizeAutomatically (use _fAutosolve from parent, instead).
+
+ * guile/cassowary_scm.hpp, guile/cassowary_scm.cc: Drop extra
+ include of guile/gh.h
+
+ * guile/cassowary_scm.cc: Added `cl-set-auto-solve!',
+ `cl-set-auto-reset-stay-constants!'
+
+Sat Jan 29 17:45:32 2000 Greg J. Badros <gjb@cs.washington.edu>
+
+ * configure.in (CASSOWARY_VERSION): Bump to 0.55.
+
+Sat Jan 29 17:43:05 2000 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/ClSimplexSolver.cc (Resolve): Do not comment out
+ "ResetStayConstants()" as Beurivé had done. This was resulting in
+ quirky behaviour whereby the windows were "rubber-banding" back to
+ where they were at the start of an interaction (e.g., if I push a
+ window out of the way to the left with another window, as I move
+ the pushing window back to the right, the other window comes back
+ to the right with the pushing window). Maybe that's desirable
+ behaviour in some instances, but it's not the behaviour we
+ document and sure feels weird to me.
+
+Sat Jan 29 17:38:43 2000 Greg J. Badros <gjb@cs.washington.edu>
+
+ * java/sym.java, java/parser.java, java/Yylex.java: Added -- these
+ are created by JavaCUP which I don't want to be necessary for
+ building.
+
+Mon Jan 24 09:34:20 2000 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/ClSymbolicWeight.h: Set SymbolicWeight multiplier to
+ 1000000, not 10000 (A.Beurivé)
+
+ * c++/ClSimplexSolver.h, c++/ClSimplexSolver.cc: Added
+ ChangeStrength, ChangeStrengthAndWeight, ChangeWeight,
+ DisplayObjective, ExternalResetStayConstants fns.
+ (RemoveConstraintInternal) Avoid picking the objective row when
+ removing a constraint. (Optimize) Pick any negative row to avoid
+ unending pivots [I think this is a work-around to avoid having to
+ implement Bland's anti-cycling rule... maybe I should just do
+ that, though]. (A.Beurivé)
+
+Thu Dec 16 11:12:34 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * configure.in: Version bumped to 0.54a
+
+Thu Dec 16 11:10:42 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * java/Makefile.am: Force prefix ordering in SUBDIRS so that "."
+ dir gets built before the demos subdirectory.
+
+ * smalltalk/Makefile.am: Fix .dat file -- thanks Alan!
+
+Wed Dec 15 19:31:48 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * java/README: More notes re: security problems w/ Java 2.
+
+ * java/cda/Makefile.am: Added run target to ease running it.
+
+ * Makefile.am (EXTRA_DIST): Added c++/{config.h.in,stamp-h.in}
+
+ * java/cda/Makefile.am (EXTRA_DIST): Clean up install of .gif
+ files.
+
+ * java/Makefile.am (EXTRA_DIST): Added ClReader.{cup,lex}
+
+ * c++/Makefile.am: Do not make symlink to cassowary; let
+ configure.in do that.
+
+Wed Dec 15 18:13:14 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * java/Makefile.am: Put SUBDIRS demo cda back in since they
+ compile now.
+
+ * scripts/recreate-symlinks: Update with links to ../../EDU from
+ demo directories for Java code. Use ln -sf, not just ln -s, to avoid
+ warnings.
+
+ * Makefile.am (EXTRA_DIST): Include scripts/recreate-symlinks
+
+ * configure.in: Run recreate-symlinks script.
+
+Wed Dec 15 18:07:27 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * java/cda/Makefile.am: Put Constraint/*, Main/* files into the
+ distribution and build with them.
+
+ * java/demos/*.java: Move everything into the
+ EDU.Washington.grad.gjb.cassowary_demos package.
+
+ * java/cda/classes/run.html, java/demos/quaddemo.htm: Fix nl
+ convention, name class explicitly w/ package in front, w/o
+ trailing .class.
+
+ * java/cda/**: Move everything into the
+ EDU.Washington.grad.noth.cda package.
+
+Wed Dec 15 17:21:08 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * java/Makefile.am: Build java parser.
+
+ * java/ClParseTest.java: Added.
+
+ * GTL.h.patch: Added -- need by gcc-2.95 when compiling GTL-0.3.1
+
+ * java/README: Mention java parser.
+
+ * java/ClReader.lex, java/ClReader.cup: Cleanup, guard debug messages.
+
+Tue Dec 14 11:15:01 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * configure.in: Fix -fpermissive test to not check "cc" as well as
+ $CC. Eliminate the --enable-permissive flag since it is no longer
+ necessary.
+
+Mon Dec 13 15:56:19 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * java/Yylex.java: Added, from Will Portnoy.
+
+ * java/ClReader.cup, java/ClReader.lex: Latest version from Will,
+ cleaned up line breaks, set a tab-width for Emacs.
+
+Mon Dec 13 15:55:59 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile.am: Remove ClReader.cc -- why did I add this
+ before?
+
+Fri Dec 10 13:29:00 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * java/ClSimplexSolver.java (addLowerBound, addUpperBound): Fix
+ these two functions to call addConstraint before returning.
+ Thanks Stephen Allain for catching this! Updated exception specs
+ for those methods and for addBounds.
+
+Tue Dec 7 08:42:34 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * smalltalk/A991206.dat: New image from Alan. Include correct
+ version of code for "ClSimplexSolver removeConstraint:" to fix bug
+ when deleting constraints with weights other than 1. Also
+ disallow invalid comparisons between symbolic weights and floats.
+ Replace expressions "x clApprox: 0.0" with "x clApproxZero", which
+ works correctly for both symbolic weights and floats.
+
+ * smalltalk/*.st: Added from Alan.
+
+Mon Nov 29 16:23:06 1999 <gjb@cs.washington.edu>
+
+ * configure.in: Bump to version 0.54, added -lGTL to GTL_LIB even
+ when no --with-gtl option is given. No longer create README from
+ README.in. Added --enable-static-library option, off by default.
+
+ * c++/Makefile.am (sources): Added ClReader.cc
+
+ * cassowary.spec.in, cassowary-both.spec.in: No longer need the
+ --enable-guile-build option; it's the default now.
+
+Mon Nov 29 10:52:49 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile.am: Added use of AM_CONDITIONAL
+ CL_BUILD_STATIC_LIBRARY; only buile libcassowary.a if that option
+ was selected.
+
+ * guile/Makefile.am (libconstraints_la_LIBADD): Added @GTL_LIB@ to
+ make the guile library work with the FD-enabled version of the library.
+
+Sat Nov 27 16:11:10 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * configure.in: Invert sense of --enable-guile-build and call it
+ --disable-guile-build; build guile wrapper automatically if
+ guile-config works.
+
+Sat Nov 27 15:20:03 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * configure.in: Use an AM_CONDITIONAL for CL_BUILD_FD_SOLVER, not
+ an AC_DEFINE. Also, remove duplicate AC_SUBST of GTL_LIB, and fix
+ AM_CONDITIONAL of CL_BUILD_TESTS.
+
+Sat Nov 27 15:19:20 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile.am: Try separating out FD stuff better, and use
+ CL_BUILD_FD_SOLVER AM_CONDITIONAL to control dependence on that
+ code.
+
+ * c++/config.h.in: Drop CL_BUILD_FD_SOLVER; it's now an
+ AM_CONDITIONAL instead of a define.
+
+Wed Nov 24 15:40:27 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/ClSimplexSolver.cc: Fix typo in a throw message.
+
+ * c++/ClLinearInequality.h: Throw an editmisuse when a
+ ClLinearInequality is created w/o an inequality operator.
+
+Tue Nov 23 16:54:05 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * configure.in: Use guile's pkglibdir, not pkgdatadir, for
+ choosing cassoguiledir.
+
+Tue Nov 16 17:35:54 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * java/ClReader.lex, java/ClReader.cup: Added -- code by Will
+ Portnoy for adding a parser to the Java implementation. Untested,
+ and an early version that he emailed me.
+
+Tue Nov 16 17:34:00 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * java/ClTestColumns.java, java/ClTests.java: Put in the cassowary
+ package, instead of importing cassowary.*; jikes needed this
+ (discovered during testing of java-ml work).
+
+Sat Nov 13 11:43:48 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * java/Timer.java (Timer): Remove return type from Timer()
+ constructor (jikes caught the bug when I used this as a test case
+ for my java-ml work).
+
+Sun Oct 24 13:17:14 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * configure.in: Updated version to 0.53, generate
+ smalltalk/Makefile from Makefile.am.
+
+ * NEWS: Updated for 0.53 release.
+
+ * Makefile.am: Added smalltalk directory to SUBDIRS.
+
+Sat Oct 23 14:34:27 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * COPYING.GPL: Added
+
+ * LICENSE: Added Scwm exception
+
+
+Sat Oct 23 14:33:48 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile.am: Make cassowary/ directory symlink as needed.
+
+Sun Oct 3 16:50:43 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/ClSimplexSolver.cc: Use clvNil some places instead of NULL.
+ This is important for newer, pickier gcc-2.95.x. Thanks Alexandre
+ Duret-Lutz for the patch!
+
+Thu Sep 30 08:17:16 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/ClFDSolver.cc: Added missing #include <stdarg.h> -- Thanks
+ Harry Hochheiser for bug report.
+
+Sun Sep 26 13:43:12 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile.am (libcassowary_la_LDFLAGS): Added -version-info
+ flag to make libcassowary.so.0.0.1, instead of .0.0.0
+
+Sun Sep 26 13:15:32 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * README, ANNOUNCE: Removed
+
+ * README.in, ANNOUNCE.in: Added
+
+ * configure.in: Create README, ANNOUNCE, bump to 0.52post
+
+Sat Sep 25 16:02:22 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * cassowary.spec.in, configure.in: Update to version 0.52.
+
+Fri Sep 24 18:51:42 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * configure.in: Remove first of redundant checks for HAVE_SCM_MAKE_SMOB_TYPE_MFPE.
+
+Mon Sep 20 13:36:45 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * guile/cassowary_scm.cc: Fix `cl-int-value' to use gh_int2scm
+ instead of gh_double2scm
+
+Sun Sep 19 14:45:59 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/ClSimplexSolver.h, c++/ClSimplexSolver.cc: Replace
+ _editVarMap with _editInfoList, a list. Make ClEditInfo class
+ contain the variable since its no longer stored as values in a
+ hash where the key is the variable. Drop the index from
+ ClEditInfo. Rename ClVarToEditInfoMap to ClEditInfoList.
+
+Sun Sep 19 14:44:00 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/ClTests.cc (multiedit2): Added this new test to check nested
+ edits that share an existing variable better. This tests the fix
+ for the ScwmButtons auto-orientation seg-fault bug in Scwm.
+
+ * c++/ClBug0.cc: Added comment re: new bug fix.
+
+Sat Sep 18 22:31:54 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * configure.in: Added GUILE_LIBS setting.
+
+ * cassowary.spec.in: Use fake_root_for_install to get the
+ cassowary guile library in proper place.
+
+ * autogen.sh: Only create symlink if not already created.
+
+ * acconfig.h, c++/config.h.in: Added HAVE_SCM_MAKE_SMOB_TYPE_MFPE
+
+ * README: Added note re: enable-permissive
+
+ * guile/cassowary_scm.cc: Use new-style (guile-1.3.2 or better)
+ SMOBs conditioning on HAVE_SCM_MAKE_SMOB_TYPE_MFPE.
+
+Wed Sep 8 20:03:25 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * cassowary.spec.in: Bump to release 8
+
+ * cassowary-nofd.spec2.in: Bump to release 2.
+
+Wed Sep 8 19:43:53 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile.am: Drop building of config-inline.h -- let
+ configure handle that-- this was causing a double-build
+ (!!!ugh!!!) of Cassowary when building from RPMs, e.g.
+
+ * GTL.spec.in: Use install-strip target.
+
+Tue Sep 7 23:34:49 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * configure.in, Makefile.am: use cassowary-nofd.spec2.in
+
+ * cassowary-nofd.spec2.in: Renamed from cassowary-nofd.spec.in,
+ since having two *.spec files in the top level upsets rpm (it cats
+ them together and then gets confused by the double .spec file).
+
+ * cassowary-both.spec.in: Added-- rpm doesn't support two %build
+ tags (one for a subpackage), but if it did, this is what the
+ corresponding .spec file might look like.
+
+Tue Sep 7 23:02:26 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * Makefile.am: Added cassowary-nofd.spec to EXTRA_DIST,
+ bin_SCRIPTS = cassowary-config. Added dist-nofd target, and
+ supporting targets.
+
+ * cassowary.spec.in: Bump to 7, provide virtual package, install
+ %{prefix}/bin/* (for cassowary-config script).
+
+ * configure.in: Added CASSOWARY_VERSION variable, create
+ cassowary-config, cassowary-nofd.spec
+
+ * cassowary-config.in, cassowary-nofd.spec.in: Added
+
+Mon Sep 6 21:40:58 1999 <gjb@cs.washington.edu>
+
+ * cassowary.spec.in: Use install-strip target to remove debug
+ symbols and save disk space. Remove %{prefix}/doc/* from the
+ %files list as they are in the %doc listing already.
+
+Mon Sep 6 12:25:14 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * cassowary.spec.in: Use --host=alpha-linux on that platform
+ (using an %ifarch). Bump to release 6.
+
+ * GTL.spec.in: Fix the ./configure line for alpha platform (was
+ missing "--" before the "prefix" option). Bump to release 2.
+
+ * c++/ClSymbolicWeight.h, c++/ClSymbolicWeight.cc: Use int, not
+ unsigned, to remove ambiguity in ClSymbolicWeight constructor.
+
+Sat Sep 4 15:17:13 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * acconfig.h: Added NO_CC_PERMISSIVE flag.
+
+ * autogen.sh: Added #!/bin/sh - to top.
+
+ * configure.in: Test for g++/gcc -fpermissive flag. Hopefully
+ this will let it get used only where it is accepted. Some better
+ guile tests, too.
+
+ * cassowary.spec.in: Use --enable-permissive flag, bump from
+ release 3 to 5.
+
+Sat Sep 4 14:44:14 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile.am, guile/Makefile.am: Added CPPEXTRAFLAGS to
+ AM_CPPFLAGS.
+
+ * guile/Makefile.am: Guard lib_LIBRARIES with HAVE_GUILE test so
+ that guile stuff is only built when GUILE is desired and we have
+ the libraries installed.
+
+Tue Aug 31 22:16:04 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * java/demos/Makefile.am, java/cda/Makefile.am, java/Makefile.am
+ (install-javaJAVA): Do not try to install .class files if no
+ HAVE_JAVA
+
+Tue Aug 31 21:30:24 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * cassowary.spec.in: Do not use --disable-java-build, since that
+ still invokes the rule which is not what I want.
+
+ * java/demos/Makefile.am, java/cda/Makefile.am: Added bogus
+ classjava.stamp rule when no HAVE_JAVA to work around getting an
+ error when trying to run javac with no source files.
+
+ * configure.in: Fix some HAVE_JAVA bugs. Still not perfect, but better.
+
+Tue Aug 31 17:07:31 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * java/demos/Makefile.am, java/cda/Makefile.am, java/Makefile.am:
+ Added EXTRA_DIST.
+
+Tue Aug 31 16:27:41 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * configure.in (HAVA_JAVA): AC_OUTPUT the java/*/Makefiles.
+
+ * cassowary.spec.in: Use --disable-java-build ./configure option.
+ Bump to release 3.
+
+ * Makefile.am: Do not conditionally do directories-- that is
+ really broken with automake/rpm building.
+
+Tue Aug 31 16:20:45 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * java/demos/Makefile.am, java/cda/Makefile.am, java/Makefile.am
+ (java_JAVA): Guard with if HAVE_JAVE.
+
+Mon Aug 30 12:03:26 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * cassowary.spec.in: Bump to release 2
+
+ * configure.in: Drop the java/* wrappers/* from AC_OUTPUT macro--
+ this breaks java builds but make the Cassowary RPM build more
+ cleanly. I'm going to start making a separate cassowary-java
+ distribution unless I can figure out how to make automake and Java
+ co-exist more happily.
+
+Mon Aug 30 12:00:39 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/ClAbstractVariable.h: #include "cl_auto_ptr.h" and use
+ cl_auto_ptr, not auto_ptr.
+
+Mon Aug 30 10:06:50 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/cl_auto_ptr.h: Change the conditional inclusion sandwich to
+ CL_AUTO_PTR_H. Added "#define cl_auto_ptr auto_ptr" for MSVC.
+
+Thu Aug 26 22:42:50 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * cassowary.spec.in: Require guile 1.3.2, to be safe. Require GTL
+ >= 0.3.1, not gtl >= 0.3.1 (note capitalization)
+
+Thu Aug 26 14:12:42 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/ClFDSolver.h, c++/ClCTest.c, c++/ClC.h, c++/ClC.cc,
+ c++/Cassowary.h, c++/ClConstraint.h: Use LONG_MIN, not MINLONG and
+ #include <limits.h> not <values.h> since the latter is deprecated
+ (and does not work in VC++).
+
+ * THANKS: Thank Pengling He for his VC++ bug report re: values.h
+
+Thu Aug 26 14:08:46 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * configure.in (GUILE_PKGDATA_DIR): Set cassoguiledir variable,
+ and use ${prefix} prefix of GUILE_PKGDATA_DIR to be sure that rpm
+ building succeeds (was failing because it was trying to write to
+ an absolute location that guile told it to use, instead of using
+ the prefix of $RPM_BUILD_ROOT).
+
+ * c++/Makefile.am: Fix lex/yacc building dependencies.
+
+ * guile/Makefile.am (cassoguile_LTLIBRARIES): Do not set
+ cassoguiledir here-- do it in configure.in instead.
+
+Thu Aug 26 11:02:36 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * guile/Makefile.am (EXTRA_DIST), docs/Makefile.am: Added docs to
+ EXTRA_DIST.
+
+ * c++/Makefile.am: Added ClReader.l, ClReader.y to EXTRA_DIST,
+ remove ClReader.cc from sources. Added timer.h to
+ pkginclude_HEADERS.
+
+ * Makefile.am: Update EXTRA_DIST
+
+Thu Aug 26 08:45:08 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * configure.in: Write cassowary.spec, GTL.spec. Bump version to
+ 0.51.
+
+ * autogen.sh: Run configure, not config.status
+
+ * VERSION, README, NEWS, ANNOUNCE: Bump to 0.51, add date, notes.
+
+ * Makefile.am: Drop Java, Python to make easier to package. Added
+ EXTRA_DIST to include some doc files and the cassowary.spec file.
+
+Wed Aug 25 22:54:18 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile.am (pkginclude_HEADERS): cl_auto_ptr.h now, not auto_ptr.h
+
+Mon Aug 23 21:26:31 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * ltmain.sh, ltconfig, libtool, configure: Removed -- these are
+ autogenerated by autogen.sh
+
+Mon Aug 23 21:23:53 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+ * c++/ClSimplexSolver.cc: Use cl_auto_ptr, not auto_ptr.
+
+ * c++/ClAbstractVariable.h: #include <memory>, not "auto_ptr.h"
+
+ * c++/cl_auto_ptr.h: Added -- renamed from auto_ptr.h since that
+ was causing some difficulties due to the standard C++ auto_ptr template.
+
+Mon Jul 26 10:19:35 1999 Greg Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile.am (libcassowary_la_SOURCES): Remove redundant
+ listing of ClFD* files from this target.
+
+Mon Jul 26 09:41:09 1999 Greg Badros <gjb@cs.washington.edu>
+
+ * c++/Cl.h: Include ClConstraint.h, since cnLT, etc., need to be
+ defined for ClReader.y
+
+Mon Jul 26 09:22:11 1999 Greg Badros <gjb@cs.washington.edu>
+
+ * acconfig.h, configure.in: Use CL_ prefix for BUILD_FD_SOLVER and
+ HAVE_GTL.
+
+Mon Jul 26 09:17:56 1999 Greg Badros <gjb@cs.washington.edu>
+
+ * c++/config.h.in,c++/ClC.h,c++/ClC.cc,c++/Cl.h: Use CL_ prefix on
+ BUILD_FD_SOLVER and HAVE_GTL so that the config-inline.h gets the
+ right definitions.
+
+ * c++/Makefile.am: Expanded out the sources_for_fd_solver since
+ the _OBJECTS make variable doesn't get expanded properly if this
+ step is deferred until later. This breaks builds w/o FD solver,
+ but I have to get Amaya working ASAP.
+
+Mon Jul 19 17:08:03 1999 Greg Badros <gjb@cs.washington.edu>
+
+ * c++/ClSymbolicWeight.h: Increase multiplier to 10000 for
+ AsDouble-- works around the bug in resizing Scwm windows because
+ the medium stay constraints on width and height are too strong for
+ the strong edit constraint.
+
+Sun Jul 11 19:37:39 1999 Greg Badros <gjb@cs.washington.edu>
+
+ * c++/ClLinearExpression.h: Remove "class" from a typedef
+ ClMap<ClVariable,class T>. Thanks Alexandre 'Pollux' Duret-Lutz
+ for testing against a more recent egcs (gcc-2.95) that caught this
+ problem.
+
+ * configure.in: Improve checks for guile so that it uses --prefix
+ and --exec-prefix to --guile-prefix and --guile-exec-prefix
+
+Sat Jul 10 19:21:34 1999 Greg Badros <gjb@cs.washington.edu>
+
+ * autogen.sh: rm libtool stuff just in case.
+
+ * README: Updated version number, notes about building it and
+ needing GTL for fd solver.
+
+ * configure.in: Added --enable-cxx-tests, --enable-fd-solver,
+ --with-gtl; switch --disable-java-build to --enable-java-build
+
+ * acconfig.h, c++/config.h.in: Added HAVE_GTL, BUILD_FD_SOLVER options.
+
+ * c++/Makefile.am: Make only the library and ClTests get built by
+ default (other binary test programs are each big when build -g,
+ and aren't useful to the end user). Use @SOURCES_FOR_FD_SOLVER@
+ to permit a version of the toolkit to be build without the finite
+ domain subsolver.
+
+ * c++/ClC.h, c++/ClC.cc, c++/Cl.h: Add #ifdefs for no fd subsolver.
+
+Fri May 7 17:02:09 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClC.cc (CL_ClvLookup): Return NULL if varmap is NULL instead
+ of asserting it is non-NULL
+
+Thu May 6 19:02:38 1999 Greg J Badros <gjb@bowman.cs.monash.edu.au>
+
+ * c++/ClFDTests.cc: Added return type to connect1.
+
+ * c++/ClFDSolver.cc: Return *this where missing.
+
+ * c++/ClFDConnectorVariable.h: Reorder mem vars to match
+ initialization order in ctr.
+
+ * c++/ClC.h, c++/ClC.cc: Added CL_ClvIsFD.
+
+Sun May 2 10:42:00 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClReader.l: Permit "_" in identifiers (needed for env
+ variable precondition variables).
+
+ * c++/ClLinearInequality.h: Honour _fStrictInequality flag when
+ testing FIsSatisfied().
+
+ * c++/ClLinearConstraint.h: Added missing "void" return type for
+ ChangeConstant.
+
+Fri Apr 30 09:45:51 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClFDConnectorVariable.cc, c++/ClFDConnectorVariable.h:
+ Added -- support connecting the FD solver to the simplex solver
+ via a variable in the FD region that gets its value "copied" to a
+ analogous variable in the Simplex region.
+
+ * Makefile.am: Added ClFDConnectorVariable.[ch] files.
+
+ * c++/ClLinearConstraint.h: Added ChangeConstant()
+
+ * c++/ClFloatVariable.h, c++/ClFDVariable.h,
+ c++/ClFloatVariable.cc, c++/ClFDVariable.cc,
+ c++/ClAbstractVariable.h: Move _pv, SetPv(), Pv() from
+ ClFloatVariable, ClFDVariable, into common parent
+ ClAbstractVariable. Drop ClFloatVariable::SetName().
+
+ * c++/ClFDTests.cc: Added connect1 test to test
+ ClFDConnectorVariable
+
+ * c++/ClFDSolver.cc: Use 1 + value-rhs for errors to ensure that
+ strict inequalities behave reasonably.
+
+Thu Apr 29 19:29:34 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClVariable.h: Register variable in the dictionary when
+ initialized from a ClFDVariable*. Added const ClAbstractVariable
+ *operator() const.
+
+ * c++/ClSolver.h, c++/ClSimplexSolver.h: Added _fAutosolve,
+ _pfnChangeClvCallback; added default ctr to initialize. Added
+ SolveNoException(); Moved SetAutosolve(), FIsAutosolving(),
+ SetChangeClvCallback() from ClSimplexSolver up to here.
+
+ * c++/ClSolver.cc: Added PrintTo for list<FDNumber>, operator<<
+ for same.
+
+ * c++/ClSimplexSolver.cc: Test constraint with
+ FIsOkayForSimplexSolver() before trying to add it (avoids adding
+ FD constraints to the simplex solver).
+ s/_fOptimizeAutomatically/_fAutosolve/g
+
+ * c++/ClParseTest.cc: Use FCanConvertCn() before trying to.
+
+ * c++/ClFDVariable.h: Make PlfdnDomain() const and return const.
+
+ * c++/ClFDVariable.cc: PrintOn now displays value (duh!)
+
+ * c++/ClFDTests.cc: Use new ListPushOnto() instead of a bunch of
+ push_back. Added simple2, simple3.
+
+ * c++/ClFDSolver.h, c++/ClFDSolver.cc: Added ChangeClv(),
+ AddConstraintInternal(), RemoveConstraintInternal(),
+ ListPushOnto(), fDebugFDSolve var, more debugging code.
+
+ * c++/ClConstraint.h, c++/ClFDConstraint.h: Added
+ FIsOkayForSimplexSolver() returning false for FDCns, true in the
+ base class.
+
+ * c++/ClFDBinaryOneWayConstraint.h,
+ c++/ClFDBinaryOneWayConstraint.cc: Make ctr take ClConstraint
+ instead of ClLinearConstraint. Added EnsurePreconditionsForCn(),
+ FCanConvertCn(). Throw better exceptions instead of
+ ExCLEditMisue-- use new ExCLTooDifficultSpecial.
+
+ * c++/ClCTest.c: Use CL_ClvPrint instead of coding by hand.
+ Added CL_CldvNew() call.
+
+ * c++/ClC.cc, c++/ClC.h: Added FDN_EOL defn, typedefs for Number,
+ FDNumber, CL_CldvNew(), CL_FDCanConvertCn(), CL_FDCnFromCn(),
+ CL_ClvPrint(). Use CL_Solver for PfnChangeClvCallback, not CL_SimplexSolver.
+
+ * c++/ClAbstractVariable.h: Throw instead of assert(false) in base
+ class IsPivotable(), IsRestricted().
+
+Wed Apr 28 19:38:46 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClC.cc: Added CL_FDSolverNew()
+
+Wed Apr 28 19:10:32 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile.am (INCLUDES): Include @GUILE_INCLUDES@ -- actually
+ done to get cassowary libraries (GJB:FIXME::)
+
+Wed Apr 28 18:49:51 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile.am: Added ClCTest to the _PROGRAMS, and use
+ -lstdc++ on them
+
+ * c++/ClSolver.h: Expose Resolve() in base-class interface, along
+ with <<, and PrintOn.
+
+ * c++/ClSolver.cc: Added << operator.
+
+ * c++/ClC.h, c++/ClC.cc, c++/ClTest.c: Fixed bugs, use
+ CL_Solver... instead of CL_SimplexSolver... where appropriate.
+
+Wed Apr 28 17:15:47 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClSymbolicWeight.h: Make CLevels unsigned, not int, and
+ require all 3 args to the 3 double ctr to remove ambiguity.
+
+ * c++/ClSimplexSolver.h: Check constraint before adding and throw
+ an error if the constraint is no good for the SimplexSolver.
+
+ * c++/ClParseTest.cc: Don't assume a failed add is due to an
+ inconsistent system-- could be wrong kind of constraint was read
+ in.
+
+ * c++/ClLinearInequality.h: Store the strictness of the
+ inequality, since other solvers may be able to use strict ones.
+
+ * c++/ClFDSolver.cc: Fine-tune the exception objects thrown... use
+ the richer hierarchy.
+
+ * c++/ClFDBinaryOneWayConstraint.c,
+ c++/ClFDBinaryOneWayConstraint.h: Added IsStrictInequality(), get
+ the direction of the inequality correct.
+
+ * c++/ClErrors.h: Richer hierarchy of exceptions to cope with
+ solver limitations.
+
+ * c++/ClConstraint.h: Added IsStrictInequality(); have
+ ReadOnlyVars return a const ClVarSet&, not value.
+
+Wed Apr 28 12:20:47 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile.am: Added ClFDBinaryOneWayConstraint.cc.
+
+ * c++/ClReader.y, c++/ClReader.l: Added tokens GT, LT, and handle
+ them (for >, <, resp).
+
+ * c++/ClParseTest.cc: try converting to a FD constraint, and show
+ what that object is.
+
+ * c++/ClFDBinaryOneWayConstraint.h: Added ctr from a
+ ClLinearConstraint. Added IsInequality().
+
+Wed Apr 28 12:08:16 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ro-test.in: Added for testing below.
+
+ * c++/ClFDBinaryOneWayConstraint.cc: Added -- so far just a ctr
+ from a ClLinearConstraint object (since the parser hands me a
+ constraint object that is a ClLinearConstraint object).
+
+Tue Apr 27 20:35:23 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClSymbolicWeight.h, c++/ClSymbolicWeight.cc: Drop default
+ ctr, and give default arg value to CLevels of 3. Added operator*.
+
+ * c++/ClFDTests.cc: Better test.
+
+ * c++/ClFDSolver.h, c++/ClFDSolver.cc: Use SymbolicWeights for
+ errors, so hierarchy is handled (i.e., strengths on constraints
+ are honoured).
+
+ * c++/ClFDConstraint.h: Added ctr with strength, weight.
+
+ * c++/ClFDBinaryOneWayConstraint.h: Added strength, weight
+ arguments to ctr.
+
+ * c++/ClConstraint.h: Added symbolicWeight() accessor.
+
+Tue Apr 27 15:04:34 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClFDSolver.cc (RemoveConstraint): Fix some bugs-- handle nil
+ read-only variable properly, and clean up _mapVarToNode when
+ erasing nodes.
+
+Tue Apr 27 10:40:58 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClSolver.cc: Added -- wrote PrintTo, << basic impls, and
+ simple AddConstraint.
+
+ * c++/QocaBench.cc, c++/ClTests.cc, c++/ClSubgraphTest.cc,
+ ClLeakTest.cc, ClC.cc: Use Solve(), not solve()
+
+ * c++/ClVariable.h: Added DesiredValue, PlfdnDomain base-class
+ accessors, handle clvNil in PrintOn.
+
+ * c++/Makefile.am: Added ClSolver.cc, link with -lGTL, added
+ missing and new .cc, .h files.
+
+ * c++/ClTypedefs.h: added ClVarToConstraintSetMap.
+
+ * c++/ClSolver.h: Added AddConstraint{,NoException},
+ RemoveConstraint{,NoException}, Solver here to the abstract
+ interface, also the prototypes for the PrintTo and << on the
+ ClTypedefs.h types.
+
+ * c++/ClSimplexSolver.h, c++/ClSimplexSolver.cc: Solve(), not
+ solve(), move some protos in abstract base class ClSolver.
+
+ * c++/ClLinearInequality.h: Use ClCnRelation, not
+ ClInequalityOperator.
+
+ * c++/ClFDVariable.h, c++/ClFDVariable.cc: More accessors,
+ settors, comment-out non-initial-domain ctr.
+
+ * c++/ClFDTests.cc: Test more.
+
+ * c++/ClFDSolver.h, c++/ClFDSolver.cc: Almost complete, but
+ largely untested implementation.
+
+ * c++/ClFDBinaryOneWayConstraint.h: Added ctrs, setters, getters.
+
+ * c++/ClErrors.h: Fixed throw message for ExCLConstraintNotFound
+ to not refer to the tableau.
+
+ * c++/ClConstraint.h: Added ClCnRelation (was ClInequalityOperator
+ in c++/ClLinearInequality.h) and wrote StrCnRelation for printing
+ it.
+
+ * c++/Cl.h: include ClFDSolver.h
+
+ * c++/Cassowary.h : include values.h, def FDN_NOTSET (FIXME: drop this?)
+
+Sun Apr 25 18:55:26 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile.am: Added ClFDBinaryOneWayConstraint.h,
+ ClFDConstraint.h to pkginclude_HEADERS.
+
+ * c++/ClSimplexSolver.h, c++/ClSimplexSolver.cc: Added optional
+ strength argument to AddPointStays, AddPointStay fns.
+
+ * c++/ClFDVariable.h: Set _plfdnInitialDomain to avoid a warning
+ for now.
+
+ * c++/ClFDBinaryOneWayConstraint.h: Added return xo to PrintOn.
+
+ * c++/ClConstraint.h: Fix order of initializers.
+
+ * c++/ClC.h, c++/ClC.cc: Document return value for
+ CL_VarMapDelete, and do proper return.
+
+ * configure.in: Added --enable-cflags, --enable-cxxflags,
+ --enable-cppextraflags. Not tested yet.
+
+Sun Apr 25 11:46:28 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * configure.in: Bump version to .50, for FD features.
+
+Sun Apr 25 11:37:52 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile.am: Comment out the Bug sources/builds, add the FD
+ sources.
+
+ * c++/ClSimplexSolver.h: Inherit from ClSolver, too. Move SetPv,
+ Pv() out into ClSolver base class.
+
+ * c++/ClSimplexSolver.cc, c++/Cl.h: Make szCassowaryVersion a const char *.
+
+ * c++/ClReadery.y, c++/ClReader.l, c++/ClReader.h: Support "?"
+ read-only annotations, and use Constraint::AddROVars() to track
+ the ro vars of a constraint expression.
+
+ * c++/ClParseTest.cc: Show whether the constraint is added
+ successfully or if it is inconsistent.
+
+ * c++/ClLinearConstraint.h: Fix BUG-- super should be
+ ClConstraint, not ClLinearConstraint.
+
+ * c++/ClFDVariable.cc: Use <, > to delimit FD vars, not [, ].
+
+ * c++/ClConstraint.h, c++/ClConstraint.cc: Added AddROVars,
+ FIsReadOnlyVar, ReadOnlyVars.
+
+Thu Apr 22 20:18:31 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClVariable.h: Added ClVariable ctr that takes a
+ ClFDVariable*, this ambiguates returning NULL as a ClVariable, so
+ may not be a good idea, but it does make it less confusing than
+ having another overloaded version of ClVariable's ctr. Added
+ IsFloatVariable, IsFDVariable fwding fns.
+
+ * c++/ClSimplexSolver.cc: Disambiguate uses of NULL to be
+ (ClFloatVariable *)NULL.
+
+ * c++/ClFloatVariable.h: Added IsFloatVariable() to return true
+
+ * c++/ClC.h, c++/ClC.cc: Added CL_ClvLookupTrim for removing ws
+ around the var name.
+
+ * c++/ClAbstractVariable.h: Make IsPivotable, IsRestricted both
+ assert false instead of being pure virtual -- they only need to be
+ overridden if we want to permit them to be called. Added
+ IsFloatVariable(), IsFDVariable() both returning false in this
+ base class.
+
+ * c++/Cassowary.h: Added FDNumber typedef to be a long.
+
+ * c++/Makefile.am: Added ClFDVariable.{cc,h}
+
+ * c++/ClFDVariable.cc, c++/ClFDVariable.h: Added, copied from
+ ClFloatVariable and modified slightly.
+
+Tue Apr 20 10:18:32 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * smalltalk/README: Note that smalltalk implementation is now in
+ the public domain.
+
+ * README: Update to version 0.43, note about smalltalk
+ implementation being in public domain.
+
+ * LICENSE: Note about not applying to smalltalk implementation
+
+ * ANNOUNCE: Update date to today.
+
+ * *: Changed copyright to be "Greg J. Badros and Alan Borning"
+ instead of "Alan Borning and Greg J. Badros". Okayed by Alan --
+ to hopefully encourage more people to write me with their
+ questions/problems rather than Alan.
+
+Mon Apr 19 13:45:35 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * cassowary.spec: Added --with-guile-prefix
+
+Mon Apr 19 13:02:46 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClReader.l: Be a bit more careful about end of string
+ handling in YY_INPUT-- only return result = 1 if we read a
+ non-null character. Call yy_flush_buffer() before throw-ing an
+ error, so that we start anew the next time we are asked to return
+ tokens for the parser.
+
+ * c++/ClC.h, c++/ClC.cc: Added CL_SimplexSolverAddStay. (Fix typo
+ in .cc)
+
+Fri Apr 16 16:36:24 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClTests.cc, c++/ClSimplexSolver.h, c++/ClSimplexSolver.cc, : Use "RemoveConstraintNoException", not
+ "removeConstraintNoException" (fix initial caps.)
+
+ * c++/ClReader.y: Start looking for a constraint, turn on verbose
+ warnings and DEBUG option (still need to set cldebug = 1 in
+ debugger)
+
+ * c++/ClReader.h: In operator() for the lookup proc, Return
+ &clvNil() if _pmapVars is still NULL
+
+ * c++/ClC.h, c++/ClC.cc: Added CL_VariableName(..), CL_VarMapDelete(..),
+ CL_RemoveConstraint(..)
+
+
+Wed Apr 14 16:56:05 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * configure.in: Bump to .43.
+
+ * c++/ClC.cc (CL_VarMapDelete, CL_VariableName): Added new functions.
+
+ * cassowary.spec: Added, for building rpms
+
+ * c++/gdbinit-cassowary: Added a bunch of guile debugging macros.
+
+ * c++/Makefile.am: Added ClC.cc to libcassowary_a_SOURCES
+
+ * c++/ClReader.y: Turn off parser debugging messages by default
+
+ * c++/ClC.h, c++/ClC.cc: Added CL_ConstraintPrint, CL_FIsSatisfied
+ protos
+
+Wed Mar 31 17:23:18 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * wrappers/Makefile.in: Rename PYTHON_HEADERS to PYTHON_HEADER_DIR
+ so it does not get treated specially by automake (?).
+
+ * configure.in: Bump to .42. Added --disable-cpp-build,
+ --disable-java-build, and disable Python/Guile builds
+ automatically if directories cannot be found. Drop the
+ cassowary from c++/cassowary/config.h -- just use c++/config.h
+
+ * autogen.sh: do not fail if config.status is not -x.
+
+ * Makefile.am: Honour the HAVE_foo flags so that not all subdirs
+ have to be built.
+
+Mon Mar 29 21:01:21 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * ltconfig, ltmain.sh: Added -- so libtool isn't broken in
+ distributions.
+
+Mon Mar 29 20:59:17 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * configure.in: Try to undo a bash-ism. Untested on a vendor sh,
+ but still works with bash.
+
+Sat Mar 20 19:19:37 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * Release v0.41.
+
+Sat Mar 20 19:19:13 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * Added config.sub and config.guess to the repo -- they were
+ symlinks before which broke the distribution.
+
+Thu Mar 18 15:20:51 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * Release v0.4.
+
+Thu Mar 18 14:44:39 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * configure.in: Do not let config-inline.h get overwritten if it
+ is unchanged. Add some extra messages to tell status of
+ config-inline.h
+
+Thu Mar 18 12:59:02 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * README, configure.in, wrappers/Makefile.in: Added
+ --with-python-headers configure option.
+
+Thu Mar 18 12:48:55 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * README: Added notes about what to do when a subdir build fails,
+ suggest -k by default.
+
+ * guile/Makefile.am (test): Added this target for easier way to
+ run cltests.scm.
+
+ * guile/README: Updated with notes about how to run cltests.scm.
+
+ * java/Makefile.in: Fix tests build rule.
+
+Thu Mar 18 11:42:49 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * configure.in: Create config-inline.h at end of script.
+
+ * c++/Makefile.am: Do not have rule for building config-inline.h;
+ let configure script do that.
+
+Thu Mar 18 11:05:27 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/*.h: Use #include config-inline.h incantation so that header
+ files don't include config.h (since they may be included by
+ another package that has its own config.h)
+
+ * c++/*.cc: Use #include config.h as these are build-time-only
+ used and can thus rely on the full configure details.
+
+Thu Mar 18 10:57:08 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * guile/cassowary_scm.hpp: Use #include config-inline.h
+ incantation.
+
+ * guile/cassowary_scm.h: Drop including config.h; it's not
+ needed.
+
+ * guile/cassowary_scm.cc: Use cassowary/config.h, not config.h
+
+Thu Mar 18 10:29:40 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile.am: Install config-inline.h, not config.h, and
+ build config-inline.h by grepping for #define CL_ in config.h.
+ This works around the problem caused by Scwm including Cassowary
+ header files which then included cassowary's config.h and
+ conflicted with Scwm's config.h.
+
+Thu Mar 18 10:11:40 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/test-*.cc: Only #include "Cl.h"
+
+Thu Mar 18 09:50:45 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * wrappers/Makefile.in (clean): use rm -f so we don't get a
+ warning if file is missing.
+
+Thu Mar 18 09:49:35 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * java/Makefile.in: Use JAVA_CLASS_PATH configure variable. Fix
+ install target to echo a message about the install happening
+ during the build.
+
+Wed Mar 17 18:54:16 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile.am: Use libtool, and added lib_LTLIBRARIES. Put
+ benchmarks, bugs, and test programs all under $libdir/cassowary.
+ Drop cassoincludedir, as that's just pkginclude, and use
+ include_HEADERS for Cl.h and ClC.h, the main top-level includes.
+ Also install config.h.
+
+ * c++/Cassowary.h: #undef PACKAGE, VERSION before #including
+ cassowary/config.h as a cheezy workaround. (Switched from "" to
+ <>, and ../ to cassowary/ also).
+
+Wed Mar 17 18:50:49 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * configure.in: Put config.h in c++/cassowary so cassowary must do
+ #include <cassowary/config.h> so there is no filename conflict
+ with other packages including cassowary header files (e.g.,
+ Scwm). Added AM_PROG_LIBTOOL call. Set GUILE variables outside
+ of the guile-prefix ACE_ARG_PATH macro, and set GUILE_PKGDATA_DIR
+ use guile-config to find out where we should install the .so file.
+
+Wed Mar 17 18:43:08 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * guile/Makefile.am: Updated to build using libtool, and to
+ install header files. Changes name to libconstraints.* so that
+ the guile module name (cassowary constraints) works out, and set
+ it to install in the right place.
+
+Wed Mar 17 18:39:13 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * guile/cltests.scm: Added #! lines, change name of module to
+ (cassowary constraints), remove redundant `use-modules' call.
+
+ * guile/cassowary_scm.hpp: #include
+ cassowary/ClLinearExpression_fwd.h, not ClLinearExpression_fwd.h
+
+ * guile/cassowary_scm.cc: Change name of module to (cassowary
+ constraints). Make the init_cassowary_scm fn static.
+
+Wed Mar 17 07:39:10 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/Cassowary.h, c++/ClSimplexSolver.cc: Switch back to
+ including config.h (now ../config.h) from Cassowary.h, instead of
+ from ClSimplexSolver.cc.
+
+Tue Mar 16 19:56:02 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * acconfig.h: Fix missing comment closer */
+
+ * c++/Makefile.am: Added AM_CPPFLAGS = $(CPPEXTRAFLAGS)
+
+ * configure.in: Use config.h, not c++/config.h, and permit
+ --enable-warnings option to turn on compile-time warnings (uses
+ AM_CPPFLAGS in Makefile.am)
+
+Tue Mar 16 19:26:23 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * configure.in, acconfig.h: Better autoconf support, including
+ several --enable options. Added acconfig.h to support autoheader
+ doing the right thing in making config.h.in.
+
+Tue Mar 16 19:22:50 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClSimplexSolver.cc, c++/Cassowary.h: Include "config.h" from
+ here, not from Cassowary.h (still not right-- problem is scwm gets
+ the wrong config.h. Maybe config.h should be in ..?
+
+Tue Mar 16 19:21:06 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * java/README: Added note about common error when CLASSPATH is wrong.
+
+Tue Mar 16 15:51:15 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/Cassowary.h: #include "config.h"
+
+ * c++/ClSimplexSolver.cc: Use VERSION to init szCassowaryVersion.
+
+Tue Mar 16 12:44:33 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/**: Updated function names to always start with an uppercase
+ letter (follows C++ conventions, and brings API of Cassowary and
+ QOCA closer together). Used scripts/convert-ids to do the
+ conversion, along with scripts/ids-to-upper as the list of
+ conversions to do.
+
+Wed Mar 10 15:28:33 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * Release v0.32.
+
+Wed Mar 10 11:36:37 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * **/Makefile: Removed, since these are now generated by
+ autoconf from Makefile.in (which itself is generated by
+ automake from Makefile.am [only for some directories])
+
+ * configure.in:
+
+ * c++/ClBug2.cc: Added to demonstrate a bug that Anthony Beurivé
+ reported.
+
+ * c++/ClSimplexSolver.cc: Fix above-mentioned bug by changing the
+ coefficient of the added in removeConstraintInternal.
+
+ * c++/ClReader.l: Reset the lexer on failed id lookup.
+
+ * c++/ClC.cc, c++/ClC.h: Added VarMap access functionality, make
+ CL_ParseConstraint catch exceptions and return NULL on error
+ parsing.
+
+ * c++/config.h.in, c++/stamp-h.in: Added, for automake/autoconf
+ support.
+
+ * c++/Makefile.am: Improve installation support, updated for
+ ClBug2
+
+ * guile/Makefile.am: Build .x using guile-snarf
+
+ * c++/Makefile.linux: Updated for ClBug2
+
+ * c++/demos/DraggableBox.h: Do not return references to
+ ClVariable-s -- just return by value since they are a handle
+ class.
+
+ * guile/Makefile.am: changed name of library to
+ libcassowaryguile.a from libconstraints.a
+
+ * java/CL.h: Added a String description argument to assert() to
+ permit easier tracking of failures.
+
+ * java/ClSimplexSolver.java: Fix bug that Emmanuel Pietriga
+ reported -- use peek() to get at top element of _stkCedns stack
+ when removing edit variables in removeEditVarsTo(). Added
+ descriptions to assert()s and to throwing of ExCLInternalError.
+ Have the addBounds, addUpperBound, addLowerBound functions
+ propagate out ExCLInternalError-s instead of catching them and
+ printing an error message. Added messages to all assertions.
+
+ * java/ClLinearExpression.java: Added description to throwing of
+ ExCLInternalError.
+
+ * java/ClLinearInequality.java: Added description to throwing of
+ ExCLInternalError.
+
+ * java/ExCLInternalError.java: Require description of the error in
+ constructor.
+
+ * java/QuadDemo.java: Use System.err when printing errors, and
+ print the description of the exception.
+
+ * smalltalk/ClKernel.app: Fix bug with not using the weight of a
+ constraint as the negating coefficient when removing a constraint.
+
+Mon Mar 8 16:40:17 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * Added autoconf and partial automake support. Added numerous
+ Makefile.am's, renamed old Makefiles to Makefile.linux (and copied
+ to Makefile.in when I did not write a Makefile.am). Added
+ configure.in.
+
+ * guile/cassowary_scm.cc: Use ClReader.h, not creader.h (I renamed
+ the file)
+
+Fri Mar 5 16:24:05 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile, c++/Cl.h: Fix for renaming of creader.* ->
+ ClReader.*; make C libraries as part of lib, shared_lib rules.
+
+ * c++/ClReader.*: Added, renamed from creader.h, creader.y,
+ creader.l
+
+ * c++/ClTableau.h, c++/ClTableau.cc: Added
+ printExternalVariablesTo() fn.
+
+ * c++/ClSimplexSolver.cc: printExternalVariablesTo in
+ printInternalInfo.
+
+ * c++/ClParseTest.cc: DO not include ClReader.h-- Cl.h includes it
+
+ * c++/ClCTest.c: Make more like a browser-related test, use new
+ CL_TableauPrintExternalVariables()
+
+ * c++/ClC.h, ClC.cc: Added CL_Tableau,
+ CL_TableauPrintExternalVariables. Use "ends" to terminate
+ strstreams. Make Strong Stays use medium strength stays. Make
+ CL_ParseConstraint call ClsFromSz instead of parsing the char *
+ itself.
+
+Thu Mar 4 19:08:23 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClVariable.h: Add assert(pclv) before dereferencing through
+ ClVariable's pclv member.
+
+ * c++/Makefile: Added DYNLINK = yes/no variable for controlling
+ dynamic linking more easily.
+
+ * c++/ClSimplexSolver.h: Changed PfnChangeClvCallback to take a
+ ClVariable * instead of a ClVariable. This make it easier for the
+ C interface since it has "CLV" as a "ClVariable *" and cannot
+ reason about ClVariable-s because it doesn't see the struct defn.
+
+ * c++/ClC.cc, c++/ClC.h: Added CL_SimplexSolverSetEditedValue,
+ CL_SimplexSolverPrint, CL_SimplexSolverSetChangeClvCallback,
+ CL_VariableSetPv, CL_VariablePv.
+
+ * c++/ClCTest.cc: Test CL_SimplexSolverSetEditedValue, CL_SimplexSolverPrint.
+
+Wed Mar 3 17:37:17 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClSimplexSolver.h (UpdateExternalVariables): Added this
+ function to provide a publicly available way to get at setExternalVariables()
+
+ * c++/ClCTest.c, c++/ClC.h, c++/ClC.cc: Added for the beginnings
+ of a rudimentary C interface to the c++ library.
+
+ * c++/Makefile: Updated to build ClCTest, libccassowary.so (the C
+ interface to Cassowary [for Amaya, initially])
+
+Mon Mar 1 Greg J Badros <gjb@cs.washington.edu>
+
+ * Release v0.31
+
+Mon Mar 1 15:11:52 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClVariable.h: Added explict copy ctr.
+
+ * c++/ClEditConstraint.h, c++/ClStayConstraint.h: Changed output
+ format so parentheses started by super:: call to ClConstraint.h
+ are closed properly.
+
+ * c++/ClSimplexSolver.h, c++/ClSimplexSolver.cc: Undo removing a
+ pass by reference of ClVariable when used as an output argument.
+ Added printing for ClEditInfo class instancesm,
+ ClVarToEditInfoMap.
+
+Mon Mar 1 13:46:48 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * README: Updated for version 0.31.
+
+ * c++/Makefile: Added QocaBench.o to TEST_OBJS, comment out
+ CL_USE_HASH_MAP_AND_SET by default.
+
+ * c++/ClTestColumns.cc: Allocate constraint objects on heap, not
+ as temporaries on local stack
+
+ * c++/ClStayConstraint.h, c++/ClSimplexSolver.h,
+ c++/ClSimplexSolver.cc, c++/ClPoint.h, c++/ClLinearInequality.h,
+ c++/ClEditOrStayConstraint.h, c++/ClEditConstraint.h: Pass and
+ return ClVariable-s by value, not by reference. (Fixes bug in
+ QocaBench from re-use of a ClVariable object with the underlying
+ pointer different.
+
+ * c++/Cl.h: include creader.h
+
+ * c++/README: Fix spelling of deprecated, URL for WxWindows.
+
+ * c++/test-ClConstraint.cc: Comment out unused variables
+
+Mon Mar 1 12:53:02 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/qdemos/QuadDemoWindow.cc: Allocate constraint objects on
+ heap, not as temporaries on local stack.
+
+Fri Feb 26 09:16:31 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * wrappers/cassowary.i: Use .c_str() off of exception descriptions
+ to get the char * (description() now returns a string)
+
+Fri Feb 26 09:11:17 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClConstraint.h: Added FIsInSolver()
+
+ * guile/cassowary_scm.cc: Wrap cl-constraint-is-in-solver?
+
+Thu Feb 25 18:58:55 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * guile/cltests.scm: Added (use-modules..) invocation to get the
+ dynamically-loaded module so that it can be tested outside of
+ scwm. Updated to reflect changed behaviour in cl-add-stay. Added
+ some test code for make-cl-constraint-from-string.
+
+ * guile/cassowary_scm.hpp: Added ScmMakeClConstraint(..) to
+ abstract out setting "answer" for the (now) two ClConstraint ctrs.
+
+ * guile/cassowary_scm.cc: Added make-cl-constraint-from-string for
+ interfacing to the parser. Wrap
+ cl-constraint-change-{strength,weight}!. Make dynamically loadable
+ module! Fix BUG: was returning SCM_UNDEFINED instead of
+ SCM_UNSPECIFIED.
+
+ * guile/Makefile: Build libconstraints.so, and necessary directory
+ structure if neeeded.
+
+
+Thu Feb 25 18:41:34 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClSimplexSolver.h, c++/ClSimplexSolver.cc: Make constraints
+ get told when they're added/removed from a solver. This means
+ that constraints are no longer const params to add/remove
+ Constraint functions, and also that removeConstraint needs an
+ internal version that doesn't do the counting (since
+ removeConstraint can get called from addConstraint to clean up
+ after a failed addition).
+
+ * c++/ClSimplexSolver.cc: Clean up uses of ClConstraint &cn --
+ prefer ClConstraint *pcn even internally.
+
+ * c++/ClConstraint.h: Added ChangeStrength(..), ChangeWeight(..)
+ and _times_added memvar along w/ private (for friend
+ ClSimplexSolver) addedTo(..) and removedFrom(..) functions. Only
+ permit strength/weight changing if constraint is in no solvers
+ presently.
+
+ * c++/ClConstraint.cc: Output _times_added memvar in printOn(...)
+
+Thu Feb 25 15:58:27 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClErrors.h: Added parse error classes, and have description
+ return a "string" instead of a "char *"
+
+ * c++/creader.y: Use exception ExCLParseErrorMisc in clerror, Use
+ ClVarLookupFunction instead of mapVars and fAutoCreate
+
+ * c++/creader.l: Use ClVarLookupFunction instead of doing it
+ inline with mapVars and fAutoCreate; throw exceptions on errors.
+
+ * c++/creader.h: Added ClVarLookupFunction and ClVarLookupInMap
+ and use them when parsing.
+
+ * c++/Makefile: Added some dependencies for proper building of
+ .l,.y files
+
+ * c++/ClSimplexSolver.cc: Descend VarInVarSet from
+ unary_function<..,..>
+
+ * c++/ClParseTest.cc: Catch parse errors and display the message.
+ Use ClVarLookupInMap class
+
+Thu Feb 25 12:09:48 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClSimplexSolver.cc: Simplify removeConstraint to not use
+ references.
+
+ * c++/ClSimplexSolver.h: Updated a comment
+
+ * c++/ClTests.cc: Use addEditVar, beginEdit, and endEdit, instead
+ of building EditConstraints directly.
+
+Tue Feb 23 18:48:21 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/creader.y, c++/creader.h: Remove old crummy lexer. Added
+ fAutoCreate flag to PcnParseConstraint to allow parsing with
+ automatic introduction of newly-referenced variables.
+
+ * c++/creader.l: Fixed bugs in missing tokens "|", "(", ")", and
+ permit "==" as a synonym for "=". Honour the _fAutoCreate flag by
+ introducing variables when needed.
+
+ * c++/ClTests.cc: Display version id string at startup.
+
+ * c++/ClSimplexSolver.cc, c++/Cl.h: Added szCassowaryVersion id
+ string.
+
+ * c++/ClParseTest.cc: Test auto-addition of variable (fAutoCreate
+ = true)
+
+Tue Feb 23 18:12:23 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile: Build libcassowary.{a,so} by default, not
+ libcassowary-notrace.{a,so}. Remove special rule for building
+ ClParseTest; list creader-lex.o, creader.o in OBJS and have them
+ be a part of the library.
+
+ * c++/ClVariable.h, c++/ClVariable.cc: Rename pmapSzPclv to
+ pmapStrPclv. Make it a map from "const string" not "string".
+ Make setName erase the old mapping, and add the new mapping.
+
+ * c++/ClParseTest.cc: Accept "-" option to mean "rename x to foo"
+ for testing the setName change above.
+
+ * c++/ClFloatVariable.cc: Do not output warning msg in setName --
+ instead, do the right thing in ClVariable.h
+
+Tue Feb 23 08:55:28 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile: Fix build rules for bison/flex parser so
+ dependencies are correct. Added new targets, all-notests,
+ all-tests, make 'lib' the default target, and all really build
+ everything.
+
+ * c++/creader.h, c++/creader.l, c++/creader.y: Take address of
+ ClVariable-s from the map's values (cannot use ClVariable in the
+ union directly because union members cannot have constructors).
+ #include ClVariable.h instead of fwd decl of ClVariable so that we
+ get the StringToVarMap typedef, too.
+
+Mon Feb 22 16:33:16 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile: Use CL_LIBRARY, not LIB_FILE, throughout. Use
+ flags for maximum performance.
+
+ * c++/ClVariable.h, c++/ClConstraintHash.h, c++/Cassowary.h:
+ Divide pointer address by CL_PTR_HASH_DIVISOR in hash functions
+
+ * c++/ClTests.cc: Added CL_SHOW_CNS_IN_BENCHMARK guard protecting
+ new displaying of constraints and listing of inconsistent constraints.
+
+Mon Feb 22 12:18:53 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClTests.cc (inconsistent3): Drop extra redundant
+ inconsistency for pedagogical reasons. Use simpler pointer-based
+ addConstraint in benchmark test
+
+ * c++/ClSimplexSolver.h: Added addConstraintNoException,
+ removeConstraintNoException taking ClConstraint &'s -- deprecated.
+ Added CL_NO_DEPRECATED guard for turning off availability of
+ deprecated functions.
+
+Mon Feb 22 11:12:35 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClSimplexSolver.h: Added deprecated
+ FIsConstraintSatisfied(Constraint &)
+
+ * guile/cassowary_scm.cc: Use ClConstraintToVarMap for return
+ value of ConstraintMap(). Pass Constraint *'s instead of &'s.
+ Use new name printOnVerbose instead of printDebugInfo.
+
+Fri Feb 19 Greg J Badros <gjb@cs.washington.edu>
+
+ * Release v0.3.
+
+Fri Feb 19 18:00:49 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClTests.cc: Updated to fix below interface.
+
+ * c++/ClSimplexSolver.cc, c++/ClSimplexSolver.h: make
+ addConstraint, addConstraintNoException, removeConstraint,
+ removeConstraintNoException take ClConstraint *'s instead of
+ ClConstraint &'s. Clarifies the mental model, and simplifies the
+ syntax. Old style is still accepted, but is deprecated.
+
+Fri Feb 19 17:41:45 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClFloatVariable.cc, c++/ClFloatVariable.h: Added -- moved
+ here from ClVariable.h, and renamed from class ClVariableRep since
+ they not what ClVariable wraps (ClVariable wraps
+ ClAbstractVariable)
+
+ * c++/ClAbstractVariable.h: Fatten interface to include set_value,
+ change_value, setPv, and Pv.
+
+ * c++/ClVariable.h, c++/ClVariable.cc: Move ClVariableRep into
+ ClFloatVariable.{h,cc}, and use pclv-> for
+ set_value, change_value, SetPv, and Pv since ClAbstractVariable
+ now has a fat interface and we do not need to do the dynamic
+ down-casting.
+
+ * c++/Makefile: Added new files to build rules.
+
+Fri Feb 19 17:08:29 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/debug.h, c++/ClTableau.h: Move operator<< out into ClTableau.h
+
+ * c++/ClVariable.h, c++/ClVariable.cc: Move some inline functions
+ into .cc so that the hash function can go in the .h file (some stl
+ dependency issue, it seems).
+
+ * c++/ClErrors.h, c++/ClTypedefs.h: Move typedef for
+ ClConstraintSet from ClErrors.h into ClTypedefs.h, and have former
+ include the latter.
+
+ * c++/Cassowary.h: #include ClConstraintHash.h
+
+ * c++/ClConstraintHash.h: Added. The hash function needs to
+ appear before any typedef that uses a hash_map or hash_set, so
+ this file is included by Cassowary.h
+
+Fri Feb 19 08:45:24 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClSubgraphTest.cc: Fix some bugs just from not testing
+ completely.
+
+ * c++/*: Fix bugs from not-updated-code hidden by #ifdefs. Builds
+ w/ all compile-options except -DCL_USE_HASH_MAP_AND_SET. Drop
+ some gratuitous appearances of ClAbstractVariable
+
+Thu Feb 18 18:53:56 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClLinearExpression.cc: Use clvNill when returning a
+ ClVariable instead of NULL
+
+ * c++/ClVariable.h, c++/ClVariable.cc: operators ==, !=, < all should use the
+ contained pointers address, not value. Also define global clvNil,
+ isNil().
+
+ * c++/ClTests.cc: BUGFIX: #if 0 removed from adding stays in
+ simple1 test
+
+ * c++/ClSimplexSolver.h: Use ClVariable-s internally for
+ ClObjectiveVariable-s.
+
+ * c++/ClSimplexSolver.cc: Use ClVariable-s internally for
+ ClObjectiveVariable-s and replace ClAbstractVariable
+ *p{entryVar,exitVar} with ClVariable-s. (Use clvNil and isNil()
+ to test for not yet set).
+
+Thu Feb 18 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/*: First compilable and almost working version with
+ ClVariable as a handle to ClVariableRep. Major simplifications
+ throughout.
+
+Thu Feb 18 14:22:14 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile: Split out the options into += lists so they can be
+ flipped independently more easily.
+
+ * c++/ClSimplexSolver.cc, c++/ClSimplexSolver.h: Added output
+ operation for ClConstraintToVarSetMap; use fFoundErrorVar flag to
+ simplify some redundant tests in removeConstraint -- no longer use
+ errorVarsCopy.
+
+ * c++/CLVariable.h: Fix a comment's example.
+
+ * c++/ClTypedefs.h: Use set always for ClTableauVarSet (Steve
+ Wolfman notes that it's faster as a set than as a hash_set).
+
+ * c++/debug.h: Add CtrTracer, DtrTracer fns that do nothing when
+ not CL_TRACE
+
+ * c++/ClConstraint.h: Invoke CtrTracer, DtrTracer in ctr, dtr for
+ finding memory problem
+
+ * c++/ClTests.cc: Fix some long-time bugs in the use of ctrs that
+ build temporary objects whose lifetime was expected to be longer
+ than it was.
+
+ * c++/*: Invert sense of CL_NO_TRACE to CL_TRACE
+
+Wed Feb 17 12:10:28 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClTypedefs.h: Added -- factored out useful typedefs from
+ ClSimplexSolver.h, ClTableau.h and put them in this file.
+
+ * c++/ClTableau.h, c++/ClSimplexSolver.h, c++/debug.h: Use
+ ClTypedefs.h. Drop gdb_print (it uses printOn and printTo, now).
+ Renamed printDebugInfo to printOnVerbose (for generalized gdb
+ interface)
+
+ * c++/ClSimplexSolver.cc: Fix two bugs where I was modifying data
+ structures indirectly while iterating over them. Remove a delete
+ that was premature to fix another bug in optimized builds.
+
+ * c++/ClLinearExpression.h, c++/ClConstraint.h,
+ c++/ClAbstractVariable.h: Drop gdb_print().
+
+ * c++/ClSymbolicWeight.h: Use Number instead of double more consistently.
+
+Tue Feb 16 15:04:06 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/Cassowary.h,ClAbstractVariable.h,ClMap.h,ClSet.h,Makefile: Use
+ CL_USE_HASH_MAP_AND_SET, not USE_HASH_MAP_AND_SET.
+
+ * c++/Cl.h: #undef CL_TRACE_VERBOSE ifdef CL_NO_IO
+
+Tue Feb 16 14:55:12 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * java/ClVariable.java: Add setVarMap(..), getVarMap() for
+ maintaining symbol table of ClVariables. Added
+ setAttachedObject(..), getAttachedObject() for hanging something
+ off of a variable.
+
+ * java/ClConstraint.java: Added setAttachedObject(..),
+ getAttachedObject() for hanging something off of a constraint.
+
+ * java/ClTests.java: Added inconsistent3() and multiedit() tests
+
+ * java/ClSimplexSolver.java: Manage multiple (nested) edits
+ properly. Provide access to the _markerVars var through
+ getConstraintMap() accessor. Deprecate resolve(Vector) fn.
+
+Tue Feb 16 14:29:46 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * README: Updated reference to swig web site.
+
+Tue Feb 16 12:45:04 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * java/ClSimplexSolver.java, java/ClEditInfo.java, java/Makefile:
+ Fixed Michael Kaufmann's bug. (See Feb 15 note for C++ version
+ two entries below.)
+
+ * java/*.java: Updated copyright to include 1999.
+
+Tue Feb 16 10:51:01 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/*: Added CL_FIND_LEAK guard and ctr/ctr counters for
+ tracking various variable kinds.
+
+Mon Feb 15 18:38:06 1999 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClAbstractVariable.{cc,h}, ClSlackVariable.{cc,h},
+ ClDummyVariable.{cc,h}: Add counters to ctr/dtr for leakage detection.
+
+ * c++/ClSimplexSolver.{cc,h}: Replace ClConstraintAndIndex with
+ ClEditInfo, and remove ugliness of parallel vectors for edit
+ constraints. Drop _editPlusErrorVars, _editMinusErrorVars,
+ _prevEditConstants, and bundle them all up in the value end of the
+ map attached to _editVarMap. This fixes a bug reported in the
+ Java version by Michael Kaufmann long ago, and generally cleans
+ code up a bit. The resolve(vector<Number>) function is
+ deprecated, and now implemented in terms of the indices stored in
+ the new ClEditInfo class.
+
+ * c++/*: Updated copyright to include 1999.
+
+1999-02-15 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/ClVariable.{cc,h}, c++/ClAbstractVariable.h: Added
+ SetVarMap(..), VarMap(), and make variables given names get their
+ names mapped to the objects in the var map (for access when
+ parsing constraints as strings). Make setName() virtual so
+ ClVariable can override it.
+
+1999-02-12 Greg J Badros <gjb@cs.washington.edu>
+
+ * c++/creader.{y,h}: New version from Steve Wolfman, slightly
+ updated for cleaner integration. Pass in a map<string,ClVariable
+ *> instead of an array of ClVariable; improve error handling a
+ bit.
+
+ * c++/debug.h: Use ClMap, ClSet
+
+ * c++/{ClMap.h,ClSet.h}: Added, for optionally using hash_map,
+ hash_set instead of map, set.
+
+ * c++/ClSimplexSolver.{cc,h}: Added Steve Wolfman's explanation
+ support (added back map for marker->constraint, _fExplainFailure
+ var + getter & settor). Use ClMap, ClSet. Cleaned up some cerr
+ output, and use DEBUG_FAILURES cpp symbol to guard some output.
+
+ * c++/Cassowary.h: Added operator() for hash<..> to support
+ hashing things used as keys in hash_map/hash_set
+
+ * c++/ClErrors.h: Added ExCLRequiredFailureWithExplanation class
+ for explanation support.
+
+ * c++/{ClLinearExpression.h,ClTableau.h}: Use ClMap, not map. Use
+ ClSet, not set.
+
+ * c++/ClSymbolicWeight.h: Return a symbolic weight even when
+ assert(false) to avoid compiler warning.
+
+1999-02-11 Greg J Badros <gjb@cs.washington.edu>
+
+ * guile/cassowary_scm.cc: Use cl-snarf.h, not scwm-snarf.h. Use
+ CL_PROC to denote primitives, not SCWM_PROC. Use
+ CL_VAR_INIT_PERMANENT macro for variables, and document them (the
+ strength objects only, for now). Fix the default strength of
+ cl-add-editvar to Strong, not Weak, and update docs (was cut&paste
+ error from the cl-add-stay primitive). Thanks Anthony Beurivé for
+ noticing this bug, too!
+
+Sat Jan 30 Greg Badros <gjb@cs.washington.edu>
+
+ * Release v0.23.
+
+Sat Jan 30 13:16:31 1999 Greg Badros <gjb@cs.washington.edu>
+
+ * c++/ClSimplexSolver.cc: Fixed bug in removing a stay
+ constraint. Was editing a vector in place while iterating over
+ it. Now I use remove_if and erase. Thanks to Anthony Beurivé for
+ noticing the bug.
+
+ * c++/ClBug1.cc: Added -- bug report from Anthony Beurivé.
+
+Sat Jan 23 Greg Badros <gjb@cs.washington.edu>
+
+ * Release v0.22.
+
+Sat Jan 23 16:46:27 1999 Greg Badros <gjb@cs.washington.edu>
+
+ * guile/cassowary_scm.cc: Replace iarg uses with literal argument
+ index numbers. Use const_cast to avoid warnings when calling
+ ScmMakeClStrength on clsWeak,clsMedium,clsStrong,clsRequired objects
+
+Sat Jan 23 15:30:16 1999 Greg Badros <gjb@cs.washington.edu>
+
+ * c++/ClSimplexSolver.cc: Added some comments, some explanations
+ when exceptions are thrown, and some minor cleanups, bug-fixes
+
+ * c++/ClTests.cc: Added inconsistent3() test, and run it.
+
+ * c++/ClStrength.h: Added _pv memvar, and setPv(), Pv() -- needed
+ for tracking ClStrengths in guile
+
+ * guile/cassowary_scm.cc: Replace all iarg uses with the literal
+ number. Point ClStrength objects at their scheme-level object
+ using their new _pv field. Protect ClStrength objects properly.
+
+Sat Sep 19 17:08:21 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * c++/Makefile (CPPFLAGS): Added USE_GC, commented out, and added
+ OTHER_LIBS variable for linking with the gc library
+
+Sat Sep 19 17:01:16 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * c++/ClTableau.h: Added AssertValid() for testing integrity of
+ Tableau
+
+ * c++/ClSymbolicWeight.h, c++/ClStrength.h, c++/ClSlackVariable.h,
+ c++/ClLinearExpression.h, c++/ClErrors.h, c++/ClDummyVariable.h,
+ c++/ClConstraint.h, c++/ClAbstractVariable.h: Descend objects
+ from "gc" class conditioned on USE_GC* pp macros
+
+ * c++/Cassowary.h: Conditionally include gc_cpp.h ifdef USE_GC;
+ added NEWVAR and DELVAR macros for outputting debug information at
+ new/delete sites
+
+ * c++/ClSimplexSolver.h: Call AssertValid before solving
+
+ * c++/ClSimplexSolver.cc: Remove memory leak of the artificial
+ objective variable
+
+ * c++/ClLinearExpression.h: Fix gdb_print to have a newline
+
+ * c++/ClLeakTest: Added leakTest2 which more obviously leaks, and
+ use GC_gcollect() to force a collect
+
+Tue Sep 15 16:36:20 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * c++/ClTableau.h, ClTableau.cc: Handle removing vars from _columns more
+ carefully, and add gdb_print(), virtual destructor
+
+ * c++/ClLinearExpression.h, c++/ClConstraint.h,
+ c++/ClAbstractVariable.h: Added gdb_print()
+
+Tue Sep 14 Greg Badros <gjb@cs.washington.edu>
+
+ * Release v0.21.
+
+Wed Sep 9 09:46:35 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * c++/ClLinearExpression.h, c++/ClLinearExpression.cc: added uses
+ of 'typename' keyword as needed by egcs-1.1b's -pedantic (and the
+ C++ FDIS)
+
+Sun Sep 6 13:19:01 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * c++/ClSimplexSolver.h: Added _pv field, and Pv() setPv() getter
+ and setter
+
+ * guile/cassowary_scm.cc: Use solver's _pv field to point
+ ClSimplexSolver back at the scheme object that wraps it
+
+Fri Sep 4 18:52:50 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * guile/cassowary_scm.hpp, guile/cassowary_scm.cc: Added PvFromScm
+ and ScmFromPv to hide the reinterpret casts used to store a scheme
+ object as the void * Pv() attached to a cassowary object. Attach
+ the scheme-level cl-variable to a ClVariable object. Added
+ `clv-attach!' and `clv-attached-object' to manipulate the attached
+ object (often better to use scheme level properties, though)
+
+Fri Sep 4 18:51:30 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * guile/Makefile: Use "perl" from path to run extract docs instead
+ of relying on #! line, and generate the -procedures.txt file as
+ well as the .sgml file
+
+Wed Sep 2 17:08:14 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * guile/cassowary_scm.cc, guile/cassowary_scm.hpp: Added
+ ClStayConstraint wrapper. Make cl-add-stay, cl-add-editvar take a
+ list of variables instead of a varargs last argument and instead
+ add two optional arguments STRENGTH and FACTOR (thus those
+ primitives remain backward compatible as long as only one variable
+ was given).
+
+Wed Sep 2 13:55:37 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * ClSimplexSolver.h: Added weight option to addEditVar and use it
+
+ * ClLinearExpression.h: Added PconstClAbstractVariable, use it;
+ use ClVarToCoeffMap in coefficientFor.
+
+Thu Aug 6 20:56:45 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * Release v0.2.
+
+Thu Aug 6 20:41:40 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * ClTests.cc: Added multiedit() test for testing nested
+ beginEdit-s
+
+ * ClSimplexSolver.h, ClSimplexSolver.cc: Support nested
+ beginEdit-s -- use removeEditVarsTo(n), and rewrite
+ removeAllEditVars in terms of the former; Use FIsSatisfied on
+ constraint and compare with testing internally for
+ FIsConstraintSatisfied() -- untested.
+
+ * ClLinearInequality.h, ClLinearEquation.h, ClConstraint.h: Added
+ virtual FIsSatisfied
+
+ * ClLinearExpression.h, ClLinearExpression.cc: Added evaluate()
+
+ * ClAbstractVariable.h: Return 0 for value(), and make it a
+ virtual function.
+
+Wed Aug 5 16:10:56 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * ClStrength.h: Have ClStrength::symbolicWeight return a const
+ ref, instead of by value, make clsXXX const refs.
+
+ * ClSimplexSolver.cc, ClLinearInequality.cc, ClLinearEquation.cc,
+ ClLinearConstraint.cc: Take ClStrengths by const refs
+
+Tue Aug 4 15:22:08 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * guile/cassowary_scm.cc, cassowary_scm.hpp: Move all inline
+ functions into .hpp file. Added cl-is-constraint-satisfied?
+
+ * ClTableau.h: Added a rowExpression() const memfn, for
+ FIsConstraintSatisfied()
+
+ * ClSimplexSolver.h, ClSimplexSolver.cc: Added (probably broken)
+ FIsConstraintSatisfied(cn) memfn -- needs testing
+
+Sun Aug 2 16:49:34 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * ClSimplexSolver.h: Added ConstraintMap() accessor to
+ _markerVars, for cl-constraint-list guile primitive
+
+ * ClConstraint.h: Added setPv(), Pv(), and _pv field to a
+ constraint, for attaching extra information.
+
+Thu Jul 30 19:15:40 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * ClTests.cc: Added simple2, to test new EditMisuse exception on
+ editing a variable that is nowhere in the solver.
+
+ * ClTableau.h, ClTableau.cc: Be more careful about inserting into
+ _externalParametricVars; add FIsBasicVar to assist that care.
+
+ * ClSimplexSolver.cc, ClSimplexSolver.h: Added pfnCnSatCallback --
+ does nothing for now; throw an ExCLEditMisuse exception if an
+ edit constraint is added on a variable that is not in the tableau
+ (needs at least a stay constraint in the solver); replace some
+ calls to rowExpression with FIsBasicVar when the latter is the
+ intent.
+
+Thu Jul 21 Greg Badros <gjb@cs.washington.edu>
+
+ * ClVariable.h, ClVariable.cc: Added _pv field, settor and gettor.
+
+
+ABOVE CHANGES ONLY IN C++ IMPLEMENTATION AND ITS WRAPPERS
+
+Fri Jul 17 19:24:54 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * ClVariable.h, .java: Added change_value memfn, and make it virtual
+ instead of setValue -- thus subclasses can specialize behaviour
+ when the variable gets set by the solver.
+
+ * ClSimplexSolver.h, .java: Use change_value for setEditedValue if
+ the variable is not in the tableau; call resolve() before
+ removeAllEditVars in endEdit
+
+ * ClSimplexSolver.cc, .java (setExternalVariables): Use change_value
+ instead of set_value when so subclasses can override and notice a
+ changed variable
+
+Thu Jul 16 19:49:45 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * Added setEditedValue(), FContainsVariable(), and addVar() to c++
+ and Java implementations
+
+ * Fixed bug in C++ and Java in solvers lacking stay constraints
+ that was due to not-updating the external parametric variables
+ set.
+
+Fri Jul 10 09:00:15 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * Fixed bug whereby a dummy variable was being pivoted into the
+ basis because pexpr->anyVariable() didn't guarantee the variable
+ it returned was a pivotable variable -- now it's called
+ anyPivotableVariable(), and does the right thing.
+
+ * Fixed bug whereby column mappings that had no rows remained in
+ the list of columns -- now erase the column key when its value is
+ the empty set
+
+ * Fixed bug whereby constraints that threw required failure
+ exceptions remained in the tableau (a removeConstraint on a
+ constraint that failed to be added used to succeed, now it does
+ not)
+
+Monday Jun 29 16:50:00 1998 Greg Badros <gjb@cs.washington.edu>
+
+ * Release Cassowary v0.1 --- see local/POST-ANNOUNCE-TO for
+ list of places where it was announced
+
diff --git a/libs/cassowary/ClAbstractVariable.cc b/libs/cassowary/ClAbstractVariable.cc
new file mode 100644
index 0000000000..b5502d4fbb
--- /dev/null
+++ b/libs/cassowary/ClAbstractVariable.cc
@@ -0,0 +1,23 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClAbstractVariable.cc
+
+#include <cassowary/ClAbstractVariable.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+long ClAbstractVariable::iVariableNumber = 0;
+#ifdef CL_FIND_LEAK
+long ClAbstractVariable::cAbstractVariables = 0;
+#endif
+
diff --git a/libs/cassowary/ClBug0.cc b/libs/cassowary/ClBug0.cc
new file mode 100644
index 0000000000..09ca1826cb
--- /dev/null
+++ b/libs/cassowary/ClBug0.cc
@@ -0,0 +1,102 @@
+// $Id$
+
+#include <cassowary/Cl.h>
+
+/* This bug fixed --02/15/99 gjb
+ Replaced the parallel vectors for edit constraints
+ (the errorPlus..., errorMinus..., prevEditConstants vectors)
+ with a ClEditInfo class that is the Value of the _editVarMap map.
+
+ Later I realized that I need to go to a _editVars list so that
+ multiple edits on the same variable that nest are handled properly.
+ --09/19/99 gjb
+*/
+
+int main()
+{
+ ClSimplexSolver solver;
+
+ ClVariable x("x",7);
+ ClVariable y("y",8);
+ ClVariable z("z",9);
+
+ solver
+ .AddStay(x)
+ .AddStay(y)
+ .AddStay(z);
+
+ try {
+ solver.AddEditVar(x);
+ solver.AddEditVar(y);
+ solver.AddEditVar(z);
+ solver.BeginEdit();
+
+ solver.SuggestValue(x,1);
+ solver.SuggestValue(z,2);
+
+ solver.RemoveEditVar(y);
+
+ solver.SuggestValue(x,3);
+ solver.SuggestValue(z,4);
+
+ solver.EndEdit();
+
+ } catch (ExCLError &e) {
+ cerr << e.description() << endl;
+ }
+
+ cout << x << endl << y << endl << z <<endl;
+
+}
+
+#if 0 /* Message below */
+ From: "Michael Kaufmann" <Michael.Kaufmann@ubs.com>
+ To: <noth@cs.washington.edu>
+ Subject: bugreport
+ Date: Thu, 1 Oct 1998 11:40:55 +0200
+ Message-Id: <000001bded1f$973a2060$230e1fac@itc_mk.sbcs.swissbank.com>
+ Mime-Version: 1.0
+ Content-Type: text/plain;
+ charset="iso-8859-1"
+ Content-Transfer-Encoding: 7bit
+ X-Priority: 3 (Normal)
+ X-Msmail-Priority: Normal
+ X-Mailer: Microsoft Outlook 8.5, Build 4.71.2173.0
+ Importance: Normal
+ X-Mimeole: Produced By Microsoft MimeOLE V4.72.2106.4
+
+ Dear Mr Noth,
+
+ I am currently working with the Java implementation of Cassowary and found
+ the following bug:
+
+ If I Add several editConstraints, remove some of them again later and
+ perform a 'ClSimplexSolver.SuggestValue()', the indices of
+ 'ClConstraintAndIndex' in the variable 'cai' are sometimes wrong (see
+ ClSimplexSolver.SuggestValue(ClVariable v, double x), the 3rd line). This is
+ because if you remove an element from a 'java.util.Vector', and the element
+ is somewhere in the middle of the Vector, the indices of the Vector change.
+ (see java.util.Vector.removeElementAt(int index):
+
+ public final synchronized void removeElementAt(int index) {
+ if (index >= elementCount) {
+ throw new ArrayIndexOutOfBoundsException(index + " >= " +
+ elementCount);
+ }
+ else if (index < 0) {
+ throw new ArrayIndexOutOfBoundsException(index);
+ }
+ int j = elementCount - index - 1;
+ if (j > 0) {
+ System.arraycopy(elementData, index + 1, elementData, index, j);
+ }
+ elementCount--;
+ elementData[elementCount] = null; /* to let gc do its work */
+ }
+
+
+ My workaround now is, that everytime when I remove an EditVariable from the
+ Solver, I have to remove all the EditVariables and Add then the ones again,
+ that I do not want to remove.
+
+#endif
diff --git a/libs/cassowary/ClBug1.cc b/libs/cassowary/ClBug1.cc
new file mode 100644
index 0000000000..e7543757e3
--- /dev/null
+++ b/libs/cassowary/ClBug1.cc
@@ -0,0 +1,21 @@
+#include <cassowary/Cl.h>
+
+int main()
+{
+ ClVariable *var = new ClVariable();
+ ClSimplexSolver *solver = new ClSimplexSolver();
+ ClStayConstraint *stcn = new ClStayConstraint(*var,ClsWeak(),1.0);
+
+ cout << *solver;
+ solver->AddConstraint(*stcn);
+ cout << *solver;
+ solver->RemoveConstraint(*stcn);
+ cout << *solver;
+}
+/*
+The result is a segmentation fault when the constraint is removed. I
+don't understand why.
+
+Anthony Beurive'" <beurive@labri.u-bordeaux.fr>
+*/
+
diff --git a/libs/cassowary/ClBug2.cc b/libs/cassowary/ClBug2.cc
new file mode 100644
index 0000000000..3a1e424259
--- /dev/null
+++ b/libs/cassowary/ClBug2.cc
@@ -0,0 +1,130 @@
+/* $Id$
+
+From: "Anthony Beurive'" <beurive@labri.u-bordeaux.fr>
+Subject: cassowary
+To: gjb@cs.washington.edu
+Date: Tue, 9 Mar 1999 12:42:24 +0100 (CET)
+
+I believe there's a bug in cassowary. It seems to be related to the
+previous one I encountered a while ago, concerning the removal of
+constraints.
+
+The three following examples may help you to track the bug, I hope.
+
+--------------------------------------------------------------------------------
+#include "Cl.h"
+
+void main()
+{
+ ClSimplexSolver *solver = new ClSimplexSolver();
+ ClVariable *var = new ClVariable();
+ ClStayConstraint *stcn = new ClStayConstraint(*var,ClsWeak(),1.0);
+
+ solver->AddConstraint(*stcn);
+ cout << *solver;
+ solver->RemoveConstraint(*stcn);
+ cout << *solver;
+}
+--------------------------------------------------------------------------------
+This works fine.
+
+
+Now, the factor of the stay constraint is changed.
+--------------------------------------------------------------------------------
+#include "Cl.h"
+
+void main()
+{
+ ClSimplexSolver *solver = new ClSimplexSolver();
+ ClVariable *var = new ClVariable();
+ ClStayConstraint *stcn = new ClStayConstraint(*var,ClsWeak(),2.0);
+
+ solver->AddConstraint(*stcn);
+ cout << *solver;
+ solver->RemoveConstraint(*stcn);
+ cout << *solver;
+}
+--------------------------------------------------------------------------------
+The result is:
+test2: ClSimplexSolver.cc:1199: void ClSimplexSolver::Optimize(class ClVariable): Assertion \
+`pzRow != __null' failed.
+Aborted
+
+
+Now, the solver is created after the variable.
+--------------------------------------------------------------------------------
+#include "Cl.h"
+
+void main()
+{
+ ClVariable *var = new ClVariable();
+ ClSimplexSolver *solver = new ClSimplexSolver();
+ ClStayConstraint *stcn = new ClStayConstraint(*var,ClsWeak(),2.0);
+
+ solver->AddConstraint(*stcn);
+ cout << *solver;
+ solver->RemoveConstraint(*stcn);
+ cout << *solver;
+}
+--------------------------------------------------------------------------------
+This works again.
+
+
+Can you reproduce the same results? Maybe the cause is my c++
+compiler (egcs-2.90.29 980515 (egcs-1.0.3 release)). I don't know.
+
+*/
+
+#include <cassowary/Cl.h>
+
+void foo1()
+{
+ ClSimplexSolver *solver = new ClSimplexSolver();
+ ClVariable *var = new ClVariable();
+ ClStayConstraint *stcn = new ClStayConstraint(*var,ClsWeak(),1.0);
+
+ solver->AddConstraint(*stcn);
+ cout << *solver;
+ solver->RemoveConstraint(*stcn);
+ cout << *solver;
+}
+
+
+void foo2()
+{
+ ClSimplexSolver *solver = new ClSimplexSolver();
+ ClVariable *var = new ClVariable();
+ ClStayConstraint *stcn = new ClStayConstraint(*var,ClsWeak(),2.0);
+
+ solver->AddConstraint(*stcn);
+ cout << *solver;
+ solver->RemoveConstraint(*stcn);
+ cout << *solver;
+}
+
+
+void foo3()
+{
+ ClVariable *var = new ClVariable();
+ ClSimplexSolver *solver = new ClSimplexSolver();
+ ClStayConstraint *stcn = new ClStayConstraint(*var,ClsWeak(),2.0);
+
+ solver->AddConstraint(*stcn);
+ cout << *solver;
+ solver->RemoveConstraint(*stcn);
+ cout << *solver;
+}
+
+
+int main()
+{
+ cerr << "Test1: " << endl;
+ foo1();
+
+ cerr << "\nTest2: " << endl;
+ foo2();
+
+ cerr << "\nTest3: " << endl;
+ foo3();
+
+}
diff --git a/libs/cassowary/ClConstraint.cc b/libs/cassowary/ClConstraint.cc
new file mode 100644
index 0000000000..1bc6be91b3
--- /dev/null
+++ b/libs/cassowary/ClConstraint.cc
@@ -0,0 +1,32 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClConstraint.cc
+
+#include <cassowary/ClConstraint.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+#ifndef CL_NO_IO
+#include <cassowary/ClTableau.h> // for VarSet printing
+
+ostream &
+ClConstraint::PrintOn(ostream &xo) const
+{
+ // Note that the trailing "= 0)" or ">= 0)" is missing, as derived classes will
+ // print the right thing after calling this function
+ xo << strength() << " w{" << weight() << "} ta{"
+ << _times_added << "} RO" << _readOnlyVars << " " << "(" << Expression();
+ return xo;
+}
+
+#endif
diff --git a/libs/cassowary/ClDummyVariable.cc b/libs/cassowary/ClDummyVariable.cc
new file mode 100644
index 0000000000..e1e9b39c0c
--- /dev/null
+++ b/libs/cassowary/ClDummyVariable.cc
@@ -0,0 +1,12 @@
+// $Id$
+
+#include <cassowary/ClDummyVariable.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+#ifdef CL_FIND_LEAK
+long ClDummyVariable::cDummyVariables = 0;
+#endif
diff --git a/libs/cassowary/ClFDBinaryOneWayConstraint.cc b/libs/cassowary/ClFDBinaryOneWayConstraint.cc
new file mode 100644
index 0000000000..e7bf7f1089
--- /dev/null
+++ b/libs/cassowary/ClFDBinaryOneWayConstraint.cc
@@ -0,0 +1,140 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClFDBinaryOneWayConstraint.cc
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+#include <cassowary/ClFDBinaryOneWayConstraint.h>
+#include <cassowary/ClLinearConstraint.h>
+#include <cassowary/ClTypedefs.h>
+#include <cassowary/ClLinearExpression.h>
+
+
+void
+ClFDBinaryOneWayConstraint::EnsurePreconditionsForCn(const ClConstraint &cn)
+{
+ ClVarSet setRO = cn.ReadOnlyVars();
+ if (setRO.size() > 1)
+ throw ExCLTooDifficultSpecial("Only 0 or 1 read only variables are allowed");
+ const ClLinearExpression &expr = cn.Expression();
+ const ClVarToNumberMap &terms = expr.Terms();
+ if (terms.size() > 2)
+ throw ExCLTooDifficultSpecial("Cannot have more than 2 variables");
+ if (terms.size() == 0)
+ throw ExCLTooDifficultSpecial("Must have at least 1 variable");
+ if (terms.size() == 2 && setRO.size() == 0)
+ throw ExCLTooDifficultSpecial("Both variables cannot be read-write, one must be read-only");
+ if (terms.size() == 1 && setRO.size() == 1)
+ throw ExCLTooDifficultSpecial("Single read-only variable in LinearConstraint -- must not be read-only.");
+ ClVariable clv = (*terms.begin()).first;
+ /* GJB:FIXME:: iterate over all the variables */
+ if (!clv->IsFDVariable()) {
+ throw ExCLTooDifficultSpecial("FD constraint contains non-FD variables");
+ }
+}
+
+bool
+ClFDBinaryOneWayConstraint::FCanConvertCn(const ClConstraint &cn)
+{
+ try {
+ EnsurePreconditionsForCn(cn);
+ return true;
+ } catch (...) {
+ return false;
+ }
+}
+
+
+ClFDBinaryOneWayConstraint::ClFDBinaryOneWayConstraint(const ClConstraint &cn)
+ :ClFDConstraint(cn.strength(), cn.weight())
+{
+ EnsurePreconditionsForCn(cn);
+ list<FDNumber> l;
+ /* GJB:FIXME:: varargs inteface, with sentinel as first arg? */
+ l.push_back(9);
+ l.push_back(10);
+ l.push_back(12);
+ l.push_back(14);
+ l.push_back(20);
+
+ ClVarSet setRO = cn.ReadOnlyVars();
+
+ ClVariable clvRO = clvNil;
+ ClVariable clvROLinear = clvNil;
+ Number coeffRO = 0;
+
+ ClVariable clvRW = clvNil;
+ Number coeffRW = 0;
+
+ if (setRO.size() == 1) {
+ const ClVariable &clv = *(setRO.begin());
+ if (clv->IsFDVariable())
+ clvRO = clv;
+ else
+ clvRO = new ClFDVariable(clv.Name(),clv.IntValue(),l);
+ clvROLinear = clv;
+ }
+ const ClLinearExpression &expr = cn.Expression();
+ const ClVarToNumberMap &terms = expr.Terms();
+
+ for (ClVarToNumberMap::const_iterator it = terms.begin();
+ it != terms.end();
+ ++it) {
+ ClVariable clv = (*it).first;
+ if (clv == clvROLinear) {
+ coeffRO = (*it).second;
+ } else {
+ if (clv->IsFDVariable())
+ clvRW = clv;
+ else
+ clvRW = new ClFDVariable(clv.Name(),clv.Value(),l);
+ coeffRW = (*it).second;
+ }
+ }
+ assert(!clvRW.IsNil());
+ if (coeffRW == 0) {
+ throw ExCLTooDifficultSpecial("RW variable's coefficient must be non-zero");
+ }
+
+ bool fInequality = cn.IsInequality();
+ bool fStrictInequality = cn.IsStrictInequality();
+ double rhs_constant = expr.Constant();
+
+ // now we have:
+ // coeffRW * clvRW + coeffRO * clvRO <REL> rhs_constant
+ // where <REL> is >= if fInequality, or = if !fInequality
+ //
+ // need:
+ // clvRW <REL> coefficient * clvRO + constant
+ //
+ // so:
+ // coefficient = -coeffRO/coeffRW
+ // constant = rhs_constant/coeffRW
+
+ if (fStrictInequality)
+ _rel = cnGT;
+ else if (fInequality)
+ _rel = cnGEQ;
+ else
+ _rel = cnEQ;
+
+ if (coeffRW < 0)
+ _rel = ReverseInequality(_rel);
+
+ _coefficient = -coeffRO/coeffRW;
+ _constant = -rhs_constant/coeffRW;
+ _vRW = clvRW;
+ _vRO = clvRO;
+ return;
+}
diff --git a/libs/cassowary/ClFDConnectorVariable.cc b/libs/cassowary/ClFDConnectorVariable.cc
new file mode 100644
index 0000000000..e6618eb9d4
--- /dev/null
+++ b/libs/cassowary/ClFDConnectorVariable.cc
@@ -0,0 +1,29 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClFDConnectorVariable.cc
+
+#include <cassowary/ClFDConnectorVariable.h>
+#include <cassowary/ClSolver.h> // for list<FDNumber> printing
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+// Use < > for ClFDConnector-s, instead of [ ]
+#ifndef CL_NO_IO
+ostream &ClFDConnectorVariable::PrintOn(ostream &xo) const
+{
+ xo << "<" << Name() << "=" << Value()
+ << "{" << _clvFloat << "}"
+ << ":" << *PlfdnDomain() << ">";
+ return xo;
+}
+#endif
diff --git a/libs/cassowary/ClFDSolver.cc b/libs/cassowary/ClFDSolver.cc
new file mode 100644
index 0000000000..7f2d199869
--- /dev/null
+++ b/libs/cassowary/ClFDSolver.cc
@@ -0,0 +1,364 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClFDSolver.cc
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+#include <cassowary/Cassowary.h>
+#include <cassowary/ClFDSolver.h>
+#include <cassowary/ClFDBinaryOneWayConstraint.h>
+#include <cassowary/ClVariable.h>
+#include <cassowary/debug.h>
+#include <GTL/topsort.h>
+#include <pair.h>
+#include <math.h>
+#include <stdarg.h>
+
+static int fDebugFDSolve;
+
+ClFDSolver &
+ClFDSolver::AddConstraint(ClConstraint *const pcn)
+{
+ AddConstraintInternal(pcn);
+ if (_fAutosolve) Solve();
+ return *this;
+}
+
+ClFDSolver &
+ClFDSolver::RemoveConstraint(ClConstraint *const pcn)
+{
+ RemoveConstraintInternal(pcn);
+ if (_fAutosolve) Solve();
+ return *this;
+}
+
+ClFDSolver &
+ClFDSolver::AddConstraintInternal(ClConstraint *const pcn)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << *pcn << ")" << endl;
+#endif
+
+ ClFDBinaryOneWayConstraint *const pcnfd =
+ dynamic_cast<ClFDBinaryOneWayConstraint *const>(pcn);
+ if (!pcnfd) {
+ throw ExCLTooDifficultSpecial("Can only add ClFDBinaryOneWayConstraint-s to ClFDSolvers");
+ }
+ ClVariable rw = pcnfd->ClvRW();
+ ClVariable ro = pcnfd->ClvRO();
+ if (!rw.IsFDVariable()) {
+ throw ExCLTooDifficultSpecial("RW variable must be an FDVariable");
+ }
+ if (!(ro.IsNil() || ro.IsFDVariable())) {
+ throw ExCLTooDifficultSpecial("RO variable must be an FDVariable or clvNil");
+ }
+ // add the constraint to our set of cns
+ _setCns.insert(pcn);
+ // and add the constraint to the cns that affect var rw
+ assert(!rw.IsNil());
+ _mapClvToCns[rw].insert(pcn);
+
+
+ node nRw = GetVarNode(rw);
+ if (!ro.IsNil()) {
+ node nRo = GetVarNode(ro);
+ edge e = G.new_edge(nRo, nRw);
+
+ _mapCnToEdge[pcn] = e;
+
+ if (!G.is_acyclic()) {
+ /* there is a cycle... give up after cleaning up */
+ RemoveConstraint(pcn);
+ throw ExCLCycleNotAllowed();
+ }
+ }
+ return *this;
+}
+
+ClFDSolver &
+ClFDSolver::RemoveConstraintInternal(ClConstraint *const pcn)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << *pcn << ")" << endl;
+#endif
+
+ ClFDBinaryOneWayConstraint *const pcnfd =
+ dynamic_cast<ClFDBinaryOneWayConstraint *const>(pcn);
+
+ if (!pcnfd) {
+ throw ExCLInternalError("Could not downcast to a ClFDBinaryOneWayConstraint");
+ }
+
+ ClConstraintSet::iterator itCn = _setCns.find(pcnfd);
+ if (itCn == _setCns.end()) {
+ throw ExCLConstraintNotFound();
+ }
+ _setCns.erase(itCn);
+
+ ClVariable rw = pcnfd->ClvRW();
+ ClVariable ro = pcnfd->ClvRO();
+ ClConstraintSet &_cnsAffectingRW = _mapClvToCns[rw];
+ ClConstraintSet::iterator it = _cnsAffectingRW.find(pcnfd);
+ if (it == _cnsAffectingRW.end()) {
+ throw ExCLInternalError("Cannot find pcnfd");
+ }
+ _cnsAffectingRW.erase(it);
+
+ if (!ro.IsNil()) {
+ edge e = _mapCnToEdge[pcn];
+ G.del_edge(e);
+ _mapCnToEdge.erase(pcn);
+
+ if (_mapVarToNode.find(ro) != _mapVarToNode.end() &&
+ _mapVarToNode[ro].degree() == 0) {
+ G.del_node(_mapVarToNode[ro]);
+ _mapVarToNode.erase(ro);
+ }
+ }
+ if (_mapVarToNode.find(rw) != _mapVarToNode.end() &&
+ _mapVarToNode[rw].degree() == 0) {
+ G.del_node(_mapVarToNode[rw]);
+ _mapVarToNode.erase(rw);
+ }
+ if (_mapClvToCns[rw].size() == 0) {
+ _mapClvToCns.erase(rw);
+ }
+
+ return *this;
+}
+
+ClFDSolver &
+ClFDSolver::Solve()
+{
+ topsort t;
+ t.run(G);
+ topsort::topsort_iterator it = t.top_order_begin();
+ topsort::topsort_iterator end = t.top_order_end();
+ ClSymbolicWeight errorTotal;
+ ResetSetFlagsOnVariables();
+ for (; it != end; ++it) {
+ ClVariable clv = nodeToVar[*it];
+ ClFDVariable *pcldv = dynamic_cast<ClFDVariable*>(clv.get_pclv());
+#ifndef NO_FDSOLVE_DEBUG
+ if (fDebugFDSolve) {
+ if (!clv.IsNil()) cout << "node " << (*it) << " is " << clv << endl;
+ cerr << "Set from: " << endl;
+ for (ClConstraintSet::iterator itCns = _mapClvToCns[clv].begin();
+ itCns != _mapClvToCns[clv].end();
+ ++itCns) {
+ const ClConstraint *pcn = *itCns;
+ cerr << *pcn << endl;
+ }
+ cerr << endl;
+ }
+#endif
+ pair<ClSymbolicWeight,FDNumber> p = ComputeBest(pcldv);
+ ClSymbolicWeight e = p.first;
+ FDNumber v = p.second;
+ if (v == FDN_NOTSET)
+ throw ExCLRequiredFailure();
+ pcldv->ChangeValue(v);
+ pcldv->SetFIsSet(true);
+ errorTotal += e;
+ }
+ return *this;
+}
+
+/* return the best (lowest) incremental error and the value
+ at which that error occurs */
+pair<ClSymbolicWeight,FDNumber>
+ClFDSolver::ComputeBest(ClFDVariable *pcldv)
+{
+ assert(pcldv);
+ // assert(!pcldv->FIsSet()); //GJB:FIXME::
+ ClSymbolicWeight minError = ClsRequired().symbolicWeight();
+ FDNumber bestValue = FDN_NOTSET;
+ // ClVariable clv(pcldv);
+ // for each domain value
+ for (list<FDNumber>::const_iterator itVal= pcldv->PlfdnDomain()->begin();
+ itVal != pcldv->PlfdnDomain()->end();
+ ++itVal) {
+ FDNumber value = *itVal;
+ ClSymbolicWeight error;
+ const ClConstraintSet &setCns = _mapClvToCns[pcldv];
+ // for each constraint affecting *pcldv
+ for (ClConstraintSet::const_iterator itCn = setCns.begin();
+ itCn != setCns.end();
+ ++itCn) {
+ const ClConstraint *pcn = *itCn;
+ ClSymbolicWeight e = ErrorForClvAtValSubjectToCn(pcldv,value,*pcn);
+ error += e;
+ }
+ // now error is the total error for binding clv <- value
+ if (error < minError) {
+ minError = error;
+ bestValue = value;
+ }
+ }
+ // now minError is the lowest error we can get for clv
+ // and it occurs binding clv <- bestValue
+ if (bestValue == FDN_NOTSET)
+ throw ExCLRequiredFailure();
+ return pair<ClSymbolicWeight,FDNumber>(minError,bestValue);
+}
+
+ClSymbolicWeight
+ClFDSolver::ErrorForClvAtValSubjectToCn(ClFDVariable *pcldv,FDNumber value,const ClConstraint &cn)
+{
+ const ClFDBinaryOneWayConstraint *pcnFd = dynamic_cast<const ClFDBinaryOneWayConstraint*>(&cn);
+ if (!pcnFd) throw ExCLInternalError("Not a binary FD constraint.");
+ ClCnRelation rel = pcnFd->Relation();
+ double m = pcnFd->Coefficient();
+ double b = pcnFd->Constant();
+ ClVariable rw = pcnFd->ClvRW();
+ ClVariable ro = pcnFd->ClvRO();
+ assert(rw.get_pclv() == pcldv);
+ double e;
+ double x = ro.IsNil()? 0 : ro.Value();
+ // return the error in satisfying:
+ // value REL m*x + b
+ double rhs = m*x + b;
+ switch (rel) {
+ case cnLEQ:
+ if (value <= rhs) e = 0;
+ else e = 1 + value-rhs;
+ break;
+ case cnLT:
+ if (value < rhs) e = 0;
+ else e = 1 + value-rhs;
+ break;
+ case cnGEQ:
+ if (value >= rhs) e = 0;
+ else e = 1+ rhs-value;
+ break;
+ case cnGT:
+ if (value > rhs) e = 0;
+ else e = 1 + rhs-value;
+ break;
+ case cnEQ:
+ if (value == rhs) e = 0;
+ else e = 1 + fabs(rhs-value);
+ break;
+ case cnNEQ:
+ if (value != rhs) e = 0;
+ else e = 1; /* GJB:FIXME:: what makes sense here? */
+ break;
+ default:
+ e = 0; /* quiet warning */
+ assert(false);
+ }
+
+ ClSymbolicWeight err;
+ if (cn.IsRequired() && e > 0)
+ err = ClsRequired().symbolicWeight();
+ else
+ err = cn.symbolicWeight() * (e*cn._weight);
+#ifndef NO_FDSOLVE_DEBUG
+ if (fDebugFDSolve) {
+ cerr << "Error at " << value << " = " << err << endl;
+ }
+#endif
+ return err;
+}
+
+
+ClFDSolver &
+ClFDSolver::ShowSolve()
+{
+ topsort t;
+ t.run(G);
+ topsort::topsort_iterator it = t.top_order_begin();
+ topsort::topsort_iterator end = t.top_order_end();
+ for (; it != end; ++it) {
+ ClVariable clv = nodeToVar[*it];
+ if (!clv.IsNil()) cout << "Node " << (*it) << " is " << clv << endl;
+ cout << "Set from: " << endl;
+ for (ClConstraintSet::iterator itCns = _mapClvToCns[clv].begin();
+ itCns != _mapClvToCns[clv].end();
+ ++itCns) {
+ const ClConstraint *pcn = *itCns;
+ cout << *pcn << endl;
+ }
+ cout << endl;
+ }
+ return *this;
+}
+
+
+/* Turn all FDVariable FIsSet() flags to false */
+void
+ClFDSolver::ResetSetFlagsOnVariables()
+{
+ for (ClVarToConstraintSetMap::iterator it = _mapClvToCns.begin();
+ it != _mapClvToCns.end();
+ ++it) {
+ ClVariable clv = (*it).first;
+ ClFDVariable *pcldv = dynamic_cast<ClFDVariable*>(clv.get_pclv());
+ assert(pcldv);
+ pcldv->SetFIsSet(false);
+ }
+}
+
+
+ostream &
+ClFDSolver::PrintOn(ostream &xo) const
+{
+ xo << "FDSolver: "
+ << _setCns
+ << "Graph nodes, edges = " << G.number_of_nodes() << ", " << G.number_of_edges()
+ << endl;
+ return xo;
+}
+
+ostream &
+ClFDSolver::PrintInternalInfo(ostream &xo) const
+{ return xo; }
+
+
+ostream &operator<<(ostream &xo, const ClFDSolver &clfds)
+{ return clfds.PrintOn(xo); }
+
+
+//// protected member functions
+
+/* Create node for v in G, if necessary,
+ otherwise return the node we already created. */
+node
+ClFDSolver::GetVarNode(ClVariable v)
+{
+ ClMap<ClVariable,node>::iterator it = _mapVarToNode.find(v);
+ if (it == _mapVarToNode.end()) {
+ node n = G.new_node();
+ _mapVarToNode[v] = n;
+ nodeToVar[n] = v;
+ return n;
+ } else {
+ return (*it).second;
+ }
+}
+
+
+void
+ListPushOnto(list<FDNumber> *pl, ...)
+{
+ va_list ap;
+ va_start(ap, pl);
+ FDNumber n;
+ while ( (n = va_arg(ap, FDNumber)) != FDN_EOL) {
+ pl->push_back(n);
+ }
+ va_end(ap);
+}
diff --git a/libs/cassowary/ClFDVariable.cc b/libs/cassowary/ClFDVariable.cc
new file mode 100644
index 0000000000..5ab9d518b1
--- /dev/null
+++ b/libs/cassowary/ClFDVariable.cc
@@ -0,0 +1,27 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClFDVariable.cc
+
+#include <cassowary/ClFDVariable.h>
+#include <cassowary/ClSolver.h> // for list<FDNumber> printing
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+// Use < > for ClFDVariable-s, instead of [ ]
+#ifndef CL_NO_IO
+ostream &ClFDVariable::PrintOn(ostream &xo) const
+{
+ xo << "<" << Name() << "=" << Value() << ":" << *PlfdnDomain() << ">";
+ return xo;
+}
+#endif
diff --git a/libs/cassowary/ClFloatVariable.cc b/libs/cassowary/ClFloatVariable.cc
new file mode 100644
index 0000000000..a3096e4b08
--- /dev/null
+++ b/libs/cassowary/ClFloatVariable.cc
@@ -0,0 +1,25 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClFloatVariable.cc
+
+#include <cassowary/ClFloatVariable.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+#ifndef CL_NO_IO
+ostream &ClFloatVariable::PrintOn(ostream &xo) const
+{
+ xo << "[" << Name() << ":" << _value << "]";
+ return xo;
+}
+#endif
diff --git a/libs/cassowary/ClLinearExpression.cc b/libs/cassowary/ClLinearExpression.cc
new file mode 100644
index 0000000000..72383ffec1
--- /dev/null
+++ b/libs/cassowary/ClLinearExpression.cc
@@ -0,0 +1,473 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClLinearExpression.cc
+
+using namespace std;
+
+#include <cassowary/ClLinearExpression.h>
+#include <cassowary/ClSymbolicWeight.h> /// needed only to instantiate with T=ClSymbolicWeight
+#include <cassowary/ClVariable.h>
+#include <cassowary/ClTableau.h>
+#include <cassowary/ClErrors.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+template <class T>
+ClGenericLinearExpression<T>::ClGenericLinearExpression(T num) :
+ _constant(num)
+{ }
+
+// Convert from ClVariable to a ClLinearExpression
+// this replaces ClVariable::asLinearExpression
+template <class T>
+ClGenericLinearExpression<T>::ClGenericLinearExpression(ClVariable clv, T value,
+ T Constant) :
+ _constant(Constant)
+{
+ _terms[clv] = value;
+}
+
+template <class T>
+ClGenericLinearExpression<T>::~ClGenericLinearExpression()
+{ }
+
+#ifndef CL_NO_IO
+template <class T>
+ostream &
+ClGenericLinearExpression<T>::PrintOn(ostream &xo) const
+{
+ typename ClVarToCoeffMap::const_iterator i = _terms.begin();
+
+ if (!ClApprox(_constant,0.0) || i == _terms.end())
+ {
+ xo << _constant;
+ }
+ else
+ {
+ if (i == _terms.end())
+ return xo;
+ xo << (*i).second << "*" << (*i).first;
+ ++i;
+ }
+ for ( ; i != _terms.end(); ++i)
+ {
+ xo << " + " << (*i).second << "*" << (*i).first;
+ }
+ return xo;
+}
+#endif
+
+
+
+// Destructively multiply self by x.
+// (private memfn)
+template <class T>
+ClGenericLinearExpression<T> &
+ClGenericLinearExpression<T>::MultiplyMe(T x)
+{
+ _constant *= x;
+
+ typename ClVarToCoeffMap::const_iterator i = _terms.begin();
+ for ( ; i != _terms.end(); ++i)
+ {
+ _terms[(*i).first] = (*i).second * x;
+ }
+ return *this;
+}
+
+// Return a new linear expression formed by multiplying self by x.
+// (Note that this result must be linear.)
+template <class T>
+ClGenericLinearExpression<T>
+ClGenericLinearExpression<T>::Times(Number x) const
+{
+ ClGenericLinearExpression<T> result = *this;
+ return result.MultiplyMe(x);
+}
+
+// Return a new linear expression formed by multiplying self by x.
+// (Note that this result must be linear.)
+// The above function optimizes the specific case of multiplying
+// by a Constant, here is the more general case
+template <class T>
+ClGenericLinearExpression<T>
+ClGenericLinearExpression<T>::Times(const ClGenericLinearExpression<T> &expr) const
+{
+ if (IsConstant())
+ {
+ return expr.Times(_constant);
+ }
+ else if (!expr.IsConstant())
+ {
+ // neither are constants, so we'd introduce non-linearity
+ throw ExCLNonlinearExpression();
+ }
+ return Times(expr._constant);
+}
+
+
+// Return a new linear expression formed by adding x to self.
+template <class T>
+ClGenericLinearExpression<T>
+ClGenericLinearExpression<T>::Plus(const ClGenericLinearExpression<T> &expr) const
+{
+ ClGenericLinearExpression<T> result = *this;
+ result.AddExpression(expr,1.0);
+ return result;
+}
+
+// Return a new linear expression formed by subtracting x from self.
+template <class T>
+ClGenericLinearExpression<T>
+ClGenericLinearExpression<T>::Minus(const ClGenericLinearExpression<T> &expr) const
+{
+ ClGenericLinearExpression<T> result = *this;
+ result.AddExpression(expr,-1.0);
+ return result;
+}
+
+// Return a new linear expression formed by dividing self by x.
+// (Note that this result must be linear.)
+template <class T>
+ClGenericLinearExpression<T>
+ClGenericLinearExpression<T>::Divide(Number x) const
+{
+ if (ClApprox(x,0.0))
+ {
+ throw ExCLNonlinearExpression();
+ }
+ return Times(1.0/x);
+}
+
+// Return a new linear expression formed by dividing self by x.
+// (Note that this result must be linear.)
+template <class T>
+ClGenericLinearExpression<T>
+ClGenericLinearExpression<T>::Divide(const ClGenericLinearExpression<T> &expr) const
+{
+ if (!expr.IsConstant())
+ {
+ throw ExCLNonlinearExpression();
+ }
+ return Divide(expr._constant);
+}
+
+
+// Return a new linear expression (expr/this). Since the result
+// must be linear, this is permissible only if 'this' is a Constant.
+template <class T>
+ClGenericLinearExpression<T>
+ClGenericLinearExpression<T>::DivFrom(const ClGenericLinearExpression<T> &expr) const
+{
+ if (!IsConstant() || ClApprox(_constant,0.0))
+ {
+ throw ExCLNonlinearExpression();
+ }
+ return expr.Divide(_constant);
+}
+
+// Add n*expr to this expression for another expression expr.
+template <class T>
+ClGenericLinearExpression<T> &
+ClGenericLinearExpression<T>::AddExpression(const ClGenericLinearExpression<T> &expr, Number n)
+{
+ IncrementConstant(expr.Constant()*n);
+
+ typename ClVarToCoeffMap::const_iterator i = expr._terms.begin();
+ for ( ; i != expr._terms.end(); ++i)
+ {
+ AddVariable((*i).first, (*i).second * n);
+ }
+ return *this;
+}
+
+// Add n*expr to this expression for another expression expr.
+// Notify the solver if a variable is added or deleted from this
+// expression.
+template <class T>
+ClGenericLinearExpression<T> &
+ClGenericLinearExpression<T>::AddExpression(const ClGenericLinearExpression<T> &expr, Number n,
+ ClVariable subject,
+ ClTableau &solver)
+{
+ IncrementConstant(expr.Constant() * n);
+
+ typename ClVarToCoeffMap::const_iterator i = expr._terms.begin();
+ for ( ; i != expr._terms.end(); ++i)
+ {
+ AddVariable((*i).first, (*i).second * n, subject, solver);
+ }
+ return *this;
+}
+
+// Add a term c*v to this expression. If the expression already
+// contains a term involving v, Add c to the existing coefficient.
+// If the new coefficient is approximately 0, delete v.
+template <class T>
+ClGenericLinearExpression<T> &
+ClGenericLinearExpression<T>::AddVariable(ClVariable v, T c)
+{ // body largely duplicated below
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << v << ", " << c << ")" << endl;
+#endif
+ typename ClVarToCoeffMap::iterator i = _terms.find(v);
+ if (i != _terms.end())
+ {
+ // expression already contains that variable, so Add to it
+ T new_coefficient = 0;
+ new_coefficient = (*i).second + c;
+ if (ClApprox(new_coefficient,0.0))
+ {
+ // new coefficient is Zero, so erase it
+ _terms.erase(i);
+ }
+ else
+ {
+ (*i).second = new_coefficient;
+ }
+ }
+ else // expression did not contain that variable
+ {
+ if (!ClApprox(c,0.0))
+ {
+ _terms[v] = c;
+ }
+ }
+ return *this;
+}
+
+// Add a term c*v to this expression. If the expression already
+// contains a term involving v, Add c to the existing coefficient.
+// If the new coefficient is approximately 0, delete v. Notify the
+// solver if v appears or disappears from this expression.
+template <class T>
+ClGenericLinearExpression<T> &
+ClGenericLinearExpression<T>::AddVariable(ClVariable v, T c,
+ ClVariable subject,
+ ClTableau &solver)
+{ // body largely duplicated above
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << v << ", " << c << ", " << subject << ", ...)" << endl;
+#endif
+ typename ClVarToCoeffMap::iterator i = _terms.find(v);
+ if (i != _terms.end())
+ {
+ // expression already contains that variable, so Add to it
+ T new_coefficient = (*i).second + c;
+ if (ClApprox(new_coefficient,0.0))
+ {
+ // new coefficient is Zero, so erase it
+ solver.NoteRemovedVariable((*i).first,subject);
+ _terms.erase(i);
+ }
+ else
+ {
+ (*i).second = new_coefficient;
+ }
+ }
+ else // expression did not contain that variable
+ {
+ if (!ClApprox(c,0.0))
+ {
+ _terms[v] = c;
+ solver.NoteAddedVariable(v,subject);
+ }
+ }
+#ifdef CL_TRACE
+ cerr << "Now *this == " << *this << endl;
+#endif
+ return *this;
+}
+
+// Return a variable in this expression. (It is an error if this
+// expression is Constant -- signal ExCLInternalError in that case).
+template <class T>
+ClVariable
+ClGenericLinearExpression<T>::AnyPivotableVariable() const
+{
+ if (IsConstant())
+ {
+ throw ExCLInternalError("(ExCLInternalError) No pivotable variables in Constant expression");
+ }
+ typename ClVarToCoeffMap::const_iterator i = _terms.begin();
+ for ( ; i != _terms.end(); ++i)
+ {
+ ClVariable v = (*i).first;
+ if (v.IsPivotable())
+ return v;
+ }
+ return clvNil;
+}
+
+// Replace var with a symbolic expression expr that is equal to it.
+// If a variable has been added to this expression that wasn't there
+// before, or if a variable has been dropped from this expression
+// because it now has a coefficient of 0, inform the solver.
+// PRECONDITIONS:
+// var occurs with a non-Zero coefficient in this expression.
+template <class T>
+void
+ClGenericLinearExpression<T>::SubstituteOut(ClVariable var,
+ const ClGenericLinearExpression<T> &expr,
+ ClVariable subject,
+ ClTableau &solver)
+{
+#ifdef CL_TRACE
+ cerr << "* ClGenericLinearExpression::";
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << var << ", " << expr << ", " << subject << ", "
+ << solver << ")" << endl;
+ cerr << "*this == " << *this << endl;
+#endif
+
+ typename ClVarToCoeffMap::iterator pv = _terms.find(var);
+
+#ifndef NDEBUG
+ if (pv == _terms.end())
+ {
+#ifndef CL_NO_IO
+ cerr << "SubstituteOut: pv != _terms.end()" << endl;
+ cerr << "(" << var << ", " << expr << ", " << subject << ", "
+ << ")" << endl;
+ cerr << "*this == " << *this << endl;
+#endif
+ throw "SubstituteOut: pv != _terms.end()";
+ }
+#endif
+ assert(pv != _terms.end());
+ // FIXGJB: this got thrown! assert(!ClApprox((*pv).second,0.0));
+
+ T multiplier = (*pv).second;
+ _terms.erase(pv);
+ IncrementConstant(multiplier * expr._constant);
+ typename ClVarToCoeffMap::const_iterator i = expr._terms.begin();
+ for ( ; i != expr._terms.end(); ++i)
+ {
+ ClVariable v = (*i).first;
+ T c = (*i).second;
+ typename ClVarToCoeffMap::iterator poc = _terms.find(v);
+ if (poc != _terms.end())
+ { // if oldCoeff is not nil
+#ifdef CL_TRACE
+ cerr << "Considering (*poc) == " << (*poc).second << "*" << (*poc).first << endl;
+#endif
+ // found it, so new coefficient is old one Plus what is in *i
+ T newCoeff = (*poc).second + (multiplier*c);
+ if (ClApprox(newCoeff,0.0))
+ {
+ solver.NoteRemovedVariable((*poc).first,subject);
+ _terms.erase(poc);
+ }
+ else
+ {
+ (*poc).second = newCoeff;
+ }
+ }
+ else
+ { // did not have that variable already (oldCoeff == nil)
+#ifdef CL_TRACE
+ cerr << "Adding (*i) == " << (*i).second << "*" << (*i).first << endl;
+#endif
+ _terms[v] = multiplier * c;
+ solver.NoteAddedVariable(v,subject);
+ }
+ }
+#ifdef CL_TRACE
+ cerr << "Now (*this) is " << *this << endl;
+#endif
+}
+
+// This linear expression currently represents the equation
+// oldSubject=self. Destructively modify it so that it represents
+// the equation NewSubject=self.
+//
+// Precondition: NewSubject currently has a nonzero coefficient in
+// this expression.
+//
+// NOTES
+// Suppose this expression is c + a*NewSubject + a1*v1 + ... + an*vn.
+//
+// Then the current equation is
+// oldSubject = c + a*NewSubject + a1*v1 + ... + an*vn.
+// The new equation will be
+// NewSubject = -c/a + oldSubject/a - (a1/a)*v1 - ... - (an/a)*vn.
+// Note that the term involving NewSubject has been dropped.
+//
+// Basically, we consider the expression to be an equation with oldSubject
+// equal to the expression, then Resolve the equation for NewSubject,
+// and destructively make the expression what NewSubject is then equal to
+template <class T>
+void
+ClGenericLinearExpression<T>::ChangeSubject(ClVariable old_subject,
+ ClVariable new_subject)
+{
+ _terms[old_subject] = NewSubject(new_subject);
+}
+
+inline double ReciprocalOf(double n)
+{ return 1.0/n; }
+
+// This linear expression currently represents the equation self=0. Destructively modify it so
+// that subject=self represents an equivalent equation.
+//
+// Precondition: subject must be one of the variables in this expression.
+// NOTES
+// Suppose this expression is
+// c + a*subject + a1*v1 + ... + an*vn
+// representing
+// c + a*subject + a1*v1 + ... + an*vn = 0
+// The modified expression will be
+// subject = -c/a - (a1/a)*v1 - ... - (an/a)*vn
+// representing
+// subject = -c/a - (a1/a)*v1 - ... - (an/a)*vn = 0
+//
+// Note that the term involving subject has been dropped.
+//
+// Returns the reciprocal, so that NewSubject can be used by ChangeSubject
+template <class T>
+T
+ClGenericLinearExpression<T>::NewSubject(ClVariable subject)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << subject << ")" << endl;
+#endif
+ typename ClVarToCoeffMap::iterator pnewSubject = _terms.find(subject);
+ assert(pnewSubject != _terms.end());
+ // assert(!ClApprox((*pnewSubject).second,0.0));
+ T reciprocal = ReciprocalOf((*pnewSubject).second);
+ _terms.erase(pnewSubject);
+ MultiplyMe(-reciprocal);
+ return reciprocal;
+}
+
+template <class T>
+T
+ClGenericLinearExpression<T>::Evaluate() const
+{
+ T answer = _constant;
+ typename ClVarToCoeffMap::const_iterator i = _terms.begin();
+
+ for ( ; i != _terms.end(); ++i)
+ {
+ ClVariable v = (*i).first;
+ answer += (*i).second * v.Value();
+ }
+ return answer;
+}
+
+
+template class ClGenericLinearExpression<Number>;
+// template class ClGenericLinearExpression<ClSymbolicWeight>;
diff --git a/libs/cassowary/ClReader.l b/libs/cassowary/ClReader.l
new file mode 100644
index 0000000000..77fa13a5a1
--- /dev/null
+++ b/libs/cassowary/ClReader.l
@@ -0,0 +1,87 @@
+/* $Id$
+ Cassowary Incremental Constraint Solver
+ Original Smalltalk Implementation by Alan Borning
+ This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+ http://www.cs.washington.edu/homes/gjb
+ (C) 1998, 1999 Greg J. Badros and Alan Borning
+ See ../LICENSE for legal details regarding this software
+
+ ClReader.l - Scanner for constraint parsing.
+ By Greg J. Badros
+ */
+
+%{
+/* Get the token numbers that bison created for us
+ (uses the -d option of bison) */
+
+#include <cassowary/ClReader.h>
+#include "ClReader.cc.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+/* global variable for the istream we are reading from;
+ gets set by PcnParseConstraint */
+istream *pxi_lexer;
+
+/* Pass in an extra variable (ClParseData *) to cllex so that
+ it can look up variable names */
+#define YY_DECL int cllex(YYSTYPE *lvalp, void *YYLEX_PARAM)
+
+/* Make lexer reader from the global variable */
+#define YY_INPUT(buf,result,max_size) \
+ do { if (pxi_lexer->get(buf[0]) && buf[0] > 0) result = 1; \
+ else result = YY_NULL; } while (0)
+
+%}
+
+%option noyywrap
+
+DIGIT [0-9]
+ALPHA [A-Za-z]
+ALPHANUM [A-Za-z0-9]
+ID_OK_PUNC [-_\[\]]
+RO_ANNOTATION "?"
+ID {ALPHA}({ALPHANUM}|{ID_OK_PUNC})*({RO_ANNOTATION})?
+NUMID "{"{DIGIT}+"}"
+ws [ \t\n]+
+
+%%
+{ws} /* skip whitespace */
+\n|";" { return 0; }
+">=" { return GEQ; }
+">" { return GT; }
+"<=" { return LEQ; }
+"<" { return LT; }
+"==" { return '='; }
+"="|"-"|"+"|"*"|"/"|"("|")" { return yytext[0]; }
+
+{DIGIT}+("."{DIGIT}*)? |
+"."{DIGIT}+ { lvalp->num = strtod(yytext,0); return NUM; }
+
+{ID} { /* Lookup the variable name */
+ ClParseData *pclpd = ((ClParseData *) YYLEX_PARAM);
+ int cch = strlen(yytext);
+ ClVariable *pclv = NULL;
+ bool fReadOnly = false;
+ if (yytext[cch-1] == '?') {
+ yytext[cch-1] = '\0';
+ fReadOnly = true;
+ }
+ const string str = string(yytext);
+ pclv = pclpd->_lookup_func(str);
+ if (!pclv->IsNil()) {
+ lvalp->pclv = pclv;
+ return fReadOnly?RO_VAR:VAR;
+ } else {
+ pxi_lexer = NULL;
+ yy_flush_buffer(YY_CURRENT_BUFFER);
+ throw ExCLParseErrorBadIdentifier(str);
+ return 0;
+ }
+ }
+
+. { pxi_lexer = NULL; throw ExCLParseErrorMisc("Unrecognized character"); }
+
diff --git a/libs/cassowary/ClReader.y b/libs/cassowary/ClReader.y
new file mode 100644
index 0000000000..f9f0dca43e
--- /dev/null
+++ b/libs/cassowary/ClReader.y
@@ -0,0 +1,154 @@
+/*
+ $Id$
+
+ Cassowary Incremental Constraint Solver
+ Original Smalltalk Implementation by Alan Borning
+ This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+ http://www.cs.washington.edu/homes/gjb
+ (C) 1998, 1999 Greg J. Badros and Alan Borning
+ See ../LICENSE for legal details regarding this software
+
+ ClReader.y
+ Original implementation contributed by Steve Wolfman
+ Subsequently largely revised by Greg J. Badros
+
+ Supports parsing of read-only variables in constraints via "?" suffix
+ annotations on variables. If a variable is followed by "?" in any of
+ its occurrences in the constraint, that variable is deemed read-only
+ and entered into the constraint object as such. E.g.,
+
+ x = 2*y?
+
+ is a one-way constraint that sets x from y's value.
+
+ x = y + y?
+ and
+ x = y? + y
+
+ are identical one-way constraints with y read-only. One would prefer
+ to have it written like so:
+
+ x = y? + y?
+
+ but it need not be, and no warning or error is raised.
+*/
+
+
+%{
+ /* C Declarations */
+
+#include <cassowary/Cl.h>
+#include <string>
+#include <map>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+#ifdef USE_CRUMMY_LEXER
+string current; /* Global to help in debugging/error messages */
+#endif
+
+/* Get yyparse, yylex to have an extra argument (type void *) */
+#define YYPARSE_PARAM cl_parse_data
+#define YYLEX_PARAM cl_parse_data
+#ifndef YYERROR_VERBOSE
+#define YYERROR_VERBOSE
+#endif
+#define YYDEBUG 1
+
+%}
+
+
+/* Bison Declarations */
+
+%pure_parser
+
+%union {
+ double num;
+ const ClVariable *pclv;
+ ClLinearExpression *pcle;
+ ClConstraint *pcn;
+}
+
+%{
+int yylex(YYSTYPE *lvalp, void *YYLEX_PARAM);
+void yyerror(const char *sz);
+%}
+
+%start constraint
+
+%token <num> NUM
+%token <pclv> VAR
+%token <pclv> RO_VAR
+
+%token GEQ
+%token GT
+%token LEQ
+%token LT
+
+%type <pcle> expr
+%type <pcn> constraint equation inequality
+
+%left '-' '+'
+%left '*' '/'
+%left NEG
+
+%%
+/* Grammar Rules */
+
+constraint: equation { $$ = $1; ((ClParseData*)YYPARSE_PARAM)->_pcn = $1; }
+ | inequality { $$ = $1; ((ClParseData*)YYPARSE_PARAM)->_pcn = $1; }
+;
+
+equation: expr '=' expr { $$ = new ClLinearEquation(*$1, *$3); }
+;
+
+inequality: expr GEQ expr { $$ = new ClLinearInequality(*$1, cnGEQ, *$3); }
+ | expr LEQ expr { $$ = new ClLinearInequality(*$1, cnLEQ, *$3); }
+ | expr LT expr { $$ = new ClLinearInequality(*$1, cnLT, *$3); }
+ | expr GT expr { $$ = new ClLinearInequality(*$1, cnGT, *$3); }
+;
+
+expr: NUM { $$ = new ClLinearExpression($1); }
+ | VAR { $$ = new ClLinearExpression(*$1); }
+ | RO_VAR { $$ = new ClLinearExpression(*$1);
+ ((ClParseData*)YYPARSE_PARAM)->_readOnlyVarsSoFar.insert(*$1); }
+ | expr '+' expr { $$ = new ClLinearExpression(*$1 + *$3); }
+ | expr '-' expr { $$ = new ClLinearExpression(*$1 - *$3); }
+ | expr '*' expr { $$ = new ClLinearExpression(*$1 * *$3); }
+ | expr '/' expr { $$ = new ClLinearExpression(*$1 / *$3); }
+ | '-' expr %prec NEG { $$ = new ClLinearExpression(-1 * *$2); }
+ | '(' expr ')' { $$ = $2; }
+;
+
+%%
+
+void clerror(const char *sz)
+{
+ throw ExCLParseErrorMisc(sz);
+}
+
+extern istream *pxi_lexer;
+
+// xi is the stream from which to read the constraint.
+// aVars is an array of variables large enough to account for
+// each one that might be mentioned in a constraint
+ClConstraint *PcnParseConstraint(istream &xi, const ClVarLookupFunction &lookup_func,
+ const ClStrength &strength)
+{
+ ClParseData cl_parse_data(xi, lookup_func);
+ pxi_lexer = &xi;
+ if (yyparse(&cl_parse_data) == 0) { // success
+#ifdef DEBUG_PARSER
+ cerr << *cl_parse_data.Pcn() << endl;
+#endif
+ cl_parse_data.Pcn()->ChangeStrength(strength);
+ cl_parse_data.Pcn()->AddROVars(cl_parse_data._readOnlyVarsSoFar);
+ return cl_parse_data.Pcn();
+ }
+ else { // failed
+ return 0;
+ }
+}
diff --git a/libs/cassowary/ClSimplexSolver.cc b/libs/cassowary/ClSimplexSolver.cc
new file mode 100644
index 0000000000..424a5d5aab
--- /dev/null
+++ b/libs/cassowary/ClSimplexSolver.cc
@@ -0,0 +1,1633 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClSimplexSolver.cc
+
+using namespace std;
+
+#include <cassowary/debug.h>
+#include <cassowary/ClSimplexSolver.h>
+#include <cassowary/ClErrors.h>
+#include <cassowary/ClVariable.h>
+#include <cassowary/ClPoint.h>
+#include <cassowary/ClSlackVariable.h>
+#include <cassowary/ClObjectiveVariable.h>
+#include <cassowary/ClDummyVariable.h>
+#include <cassowary/cl_auto_ptr.h>
+
+#include <algorithm>
+#include <float.h>
+#include <sstream>
+#include <queue>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+const char *szCassowaryVersion = VERSION;
+
+// Need to delete all expressions
+// and all slack and dummy variables
+// See NewExpression -- all allocation is done in there
+ClSimplexSolver::~ClSimplexSolver()
+{
+#ifdef CL_SOLVER_STATS
+ cerr << "_slackCounter == " << _slackCounter
+ << "\n_artificialCounter == " << _artificialCounter
+ << "\n_dummyCounter == " << _dummyCounter << endl;
+ cerr << "stayMinusErrorVars " << _stayMinusErrorVars.size() << ", "
+ << "stayPlusErrorVars " << _stayPlusErrorVars.size() << ", "
+ << "errorVars " << _errorVars.size() << ", "
+ << "markerVars " << _markerVars.size() << endl;
+#endif
+ // Cannot print *this here, since local ClVariable-s may have been
+ // destructed already
+}
+
+// Add the constraint cn to the tableau
+ClSimplexSolver &
+ClSimplexSolver::AddConstraint(ClConstraint *const pcn)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << *pcn << ")" << endl;
+#endif
+
+ if (!pcn->FIsOkayForSimplexSolver()) {
+ throw ExCLTooDifficultSpecial("SimplexSolver cannot handle this constraint object");
+ }
+
+ if (pcn->IsStrictInequality()) {
+ // cannot handle strict inequalities
+ throw ExCLStrictInequalityNotAllowed();
+ }
+
+ if (pcn->ReadOnlyVars().size() > 0) {
+ // cannot handle read-only vars
+ throw ExCLReadOnlyNotAllowed();
+ }
+
+ if (pcn->IsEditConstraint())
+ {
+ ClEditConstraint *pcnEdit = dynamic_cast<ClEditConstraint *>(pcn);
+ const ClVariable &v = pcnEdit->variable();
+ if (!v.IsExternal() ||
+ (!FIsBasicVar(v) && !ColumnsHasKey(v)))
+ {
+ // we could try to make this case work,
+ // but it'd be unnecessarily inefficient --
+ // and probably easier for the client application
+ // to deal with
+ throw ExCLEditMisuse("(ExCLEditMisuse) Edit constraint on variable not in tableau.");
+ }
+ ClEditInfo *pcei = PEditInfoFromClv(v);
+ if (pcei)
+ {
+ // we need to only add a partial _editInfoList entry for this
+ // edit constraint since the variable is already being edited.
+ // otherwise a more complete entry is added later in this function
+ _editInfoList.push_back(new ClEditInfo(v, NULL, clvNil, clvNil, 0));
+ return *this;
+ }
+ }
+
+ ClVariable clvEplus, clvEminus;
+ Number prevEConstant;
+ ClLinearExpression *pexpr = NewExpression(pcn, /* output to: */
+ clvEplus,clvEminus,
+ prevEConstant);
+ bool fAddedOkDirectly = false;
+
+ try
+ {
+ // If possible Add expr directly to the appropriate tableau by
+ // choosing a subject for expr (a variable to become basic) from
+ // among the current variables in expr. If this doesn't work use an
+ // artificial variable. After adding expr re-Optimize.
+ fAddedOkDirectly = TryAddingDirectly(*pexpr);
+ }
+ catch (ExCLRequiredFailure &error)
+ {
+#ifdef CL_TRACE
+ cerr << "could not Add directly -- caught ExCLRequiredFailure error" << endl;
+#endif
+ RemoveConstraintInternal(pcn);
+ throw;
+ }
+
+ if (!fAddedOkDirectly)
+ { // could not Add directly
+ ExCLRequiredFailureWithExplanation e;
+ if (!AddWithArtificialVariable(*pexpr, e))
+ {
+#ifdef CL_DEBUG_FAILURES
+ cerr << "Failed solve! Could not Add constraint.\n"
+ << *this << endl;
+#endif
+ RemoveConstraintInternal(pcn);
+ if (FIsExplaining())
+ throw e;
+ else
+ throw ExCLRequiredFailure();
+ }
+ }
+
+ _fNeedsSolving = true;
+
+ if (pcn->IsEditConstraint())
+ {
+ ClEditConstraint *pcnEdit = dynamic_cast<ClEditConstraint *>(pcn);
+ ClVariable clv = pcnEdit->variable();
+ _editInfoList.push_back(new ClEditInfo(clv, pcnEdit, clvEplus, clvEminus,
+ prevEConstant));
+ }
+
+ if (_fAutosolve)
+ {
+ Optimize(_objective);
+ SetExternalVariables();
+ }
+
+ pcn->addedTo(*this);
+ return *this;
+}
+
+// Add weak stays to the x and y parts of each point. These have
+// increasing weights so that the solver will try to satisfy the x
+// and y stays on the same point, rather than the x stay on one and
+// the y stay on another.
+ClSimplexSolver &
+ClSimplexSolver::AddPointStays(const vector<const ClPoint *> &listOfPoints,
+ const ClStrength &strength)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+#endif
+
+ vector<const ClPoint *>::const_iterator it = listOfPoints.begin();
+ double weight = 1.0;
+ static const double multiplier = 2.0;
+ for ( ; it != listOfPoints.end(); ++it )
+ {
+ AddPointStay((*it)->X(),(*it)->Y(),strength,weight);
+ weight *= multiplier;
+ }
+ return *this;
+}
+
+ClSimplexSolver &
+ClSimplexSolver::AddPointStay(const ClPoint &clp, const ClStrength &strength, double weight)
+{
+ AddPointStay(clp.X(),clp.Y(),strength,weight);
+ return *this;
+}
+
+
+ClSimplexSolver &
+ClSimplexSolver::RemoveEditVarsTo(unsigned int n)
+{
+ queue<ClVariable> qclv;
+ ClVarSet sclvStillEditing; // Set of edit variables that we need to *not* remove
+#ifdef DEBUG_NESTED_EDITS
+ cerr << __FUNCTION__ << " " << n << endl;
+#endif
+ unsigned int i = 0;
+ for ( ClEditInfoList::const_iterator it = _editInfoList.begin();
+ (it != _editInfoList.end() && _editInfoList.size() != static_cast<unsigned int>(n));
+ ++it, ++i )
+ {
+ const ClEditInfo *pcei = (*it);
+ assert(pcei);
+#ifdef DEBUG_NESTED_EDITS
+ cerr << __FUNCTION__ << "Checking " << pcei->_clv
+ << ", index = " << i << endl;
+#endif
+ if (i >= n)
+ qclv.push(pcei->_clv);
+ else
+ sclvStillEditing.insert(pcei->_clv);
+ }
+ while (!qclv.empty())
+ {
+ ClVariable clv = qclv.front();
+ // only remove the variable if it's not in the set of variable
+ // from a previous nested outer edit
+ // e.g., if I do:
+ // Edit x,y
+ // Edit w,h,x,y
+ // EndEdit
+ // The end edit needs to only get rid of the edits on w,h
+ // not the ones on x,y
+ if (sclvStillEditing.find(clv) == sclvStillEditing.end())
+ {
+#ifdef DEBUG_NESTED_EDITS
+ cerr << __FUNCTION__ << ": Removing " << clv << endl;
+#endif
+ RemoveEditVar(clv);
+ }
+#ifdef DEBUG_NESTED_EDITS
+ else
+ {
+ cerr << __FUNCTION__ << ": Not removing " << clv << endl;
+ }
+#endif
+ qclv.pop();
+ }
+ while (_editInfoList.size() > n) {
+ _editInfoList.pop_back();
+ }
+
+ return *this;
+}
+
+
+/* A predicate used for remove_if */
+class VarInVarSet : public unary_function<ClVariable,bool> {
+public:
+ VarInVarSet(const ClVarSet &clvset) :
+ _set(clvset),
+ _setEnd(clvset.end())
+ { }
+
+ bool operator ()(ClVariable clv) const {
+ return (_set.find(clv) != _setEnd);
+ }
+
+private:
+ const ClVarSet &_set;
+ const ClVarSet::iterator _setEnd;
+};
+
+
+
+// Remove the constraint cn from the tableau
+// Also remove any error variable associated with cn
+ClSimplexSolver &
+ClSimplexSolver::RemoveConstraintInternal(const ClConstraint *const pcn)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << *pcn << ")" << endl;
+#endif
+
+ // We are about to remove a constraint. There may be some stay
+ // constraints that were unsatisfied previously -- if we just
+ // removed the constraint these could come into play. Instead,
+ // Reset all of the stays so that things should stay where they are
+ // at the moment.
+ _fNeedsSolving = true;
+
+ ResetStayConstants();
+
+ // remove any error variables from the objective function
+ ClLinearExpression *pzRow = RowExpression(_objective);
+
+#ifdef CL_TRACE
+ cerr << _errorVars << endl << endl;
+#endif
+
+ ClConstraintToVarSetMap::iterator
+ it_eVars = _errorVars.find(pcn);
+ bool fFoundErrorVar = (it_eVars != _errorVars.end());
+
+ if (fFoundErrorVar)
+ {
+ ClVarSet &eVars = (*it_eVars).second;
+ ClVarSet::iterator it = eVars.begin();
+ for ( ; it != eVars.end(); ++it )
+ {
+ const ClLinearExpression *pexpr = RowExpression(*it);
+ if (pexpr == NULL )
+ {
+ pzRow->AddVariable(*it,-pcn->weight() * pcn->strength().symbolicWeight().AsDouble(),
+ _objective,*this);
+ }
+ else
+ { // the error variable was in the basis
+ pzRow->AddExpression(*pexpr,-pcn->weight() * pcn->strength().symbolicWeight().AsDouble(),
+ _objective,*this);
+ }
+ }
+ }
+
+ ClConstraintToVarMap::iterator
+ it_marker = _markerVars.find(pcn);
+ if (it_marker == _markerVars.end())
+ { // could not find the constraint
+ throw ExCLConstraintNotFound();
+ }
+ // try to make the marker variable basic if it isn't already
+ const ClVariable marker = (*it_marker).second;
+ _markerVars.erase(it_marker);
+ _constraintsMarked.erase(marker);
+#ifdef CL_TRACE
+ cerr << "Looking to remove var " << marker << endl;
+#endif
+ if (!FIsBasicVar(marker))
+ { // not in the basis, so need to do some work
+ // first choose which variable to move out of the basis
+ // only consider restricted basic variables
+ ClVarSet &col = _columns[marker];
+ ClVarSet::iterator it_col = col.begin();
+#ifdef CL_TRACE
+ cerr << "Must Pivot -- columns are " << col << endl;
+#endif
+
+ ClVariable exitVar = clvNil;
+ bool fExitVarSet = false;
+ double minRatio = 0.0;
+ for ( ; it_col != col.end(); ++it_col)
+ {
+ const ClVariable &v = *it_col;
+ if (v.IsRestricted() )
+ {
+ const ClLinearExpression *pexpr = RowExpression(v);
+ assert(pexpr != NULL );
+ Number coeff = pexpr->CoefficientFor(marker);
+#ifdef CL_TRACE
+ cerr << "Marker " << marker << "'s coefficient in " << *pexpr << " is "
+ << coeff << endl;
+#endif
+ // only consider negative coefficients
+ if (coeff < 0.0)
+ {
+ Number r = - pexpr->Constant() / coeff;
+ if (!fExitVarSet || r < minRatio)
+ {
+ minRatio = r;
+ exitVar = v;
+ fExitVarSet = true;
+ }
+ }
+ }
+ }
+ // if we didn't set exitvar above, then either the marker
+ // variable has a positive coefficient in all equations, or it
+ // only occurs in equations for unrestricted variables. If it
+ // does occur in an equation for a restricted variable, pick the
+ // equation that gives the smallest ratio. (The row with the
+ // marker variable will become infeasible, but all the other rows
+ // will still be feasible; and we will be dropping the row with
+ // the marker variable. In effect we are removing the
+ // non-negativity restriction on the marker variable.)
+ if (!fExitVarSet)
+ {
+#ifdef CL_TRACE
+ cerr << "exitVar did not get set" << endl;
+#endif
+ it_col = col.begin();
+ for ( ; it_col != col.end(); ++it_col)
+ {
+ ClVariable v = *it_col;
+ if (v.IsRestricted() )
+ {
+ const ClLinearExpression *pexpr = RowExpression(v);
+ assert(pexpr != NULL);
+ Number coeff = pexpr->CoefficientFor(marker);
+ Number r = pexpr->Constant() / coeff;
+ if (!fExitVarSet || r < minRatio)
+ {
+ minRatio = r;
+ exitVar = v;
+ fExitVarSet = true;
+ }
+ }
+ }
+ }
+
+ if (!fExitVarSet)
+ { // exitVar is still nil
+ // If col is empty, then exitVar doesn't occur in any equations,
+ // so just remove it. Otherwise pick an exit var from among the
+ // unrestricted variables whose equation involves the marker var
+ if (col.size() == 0)
+ {
+ RemoveColumn(marker);
+ }
+ else
+ {
+ // A. Beurive' Tue Sep 14 18:26:05 CEST 1999
+ // Don't pick the objective, or it will be removed!
+ it_col = col.begin();
+ for ( ; it_col != col.end(); ++it_col)
+ {
+ ClVariable v = *it_col;
+ if (v != _objective)
+ {
+ exitVar = v;
+ fExitVarSet = true;
+ break;
+ }
+ }
+ assert(fExitVarSet == true);
+ }
+ }
+
+ if (fExitVarSet)
+ {
+ Pivot(marker,exitVar);
+ }
+ }
+
+ if (FIsBasicVar(marker))
+ {
+ ClLinearExpression *pexpr = RemoveRow(marker);
+#ifdef CL_TRACE
+ cerr << "delete@ " << pexpr << endl;
+#endif
+ delete pexpr;
+ }
+
+ // Delete any error variables. If cn is an inequality, it also
+ // contains a slack variable; but we use that as the marker variable
+ // and so it has been deleted when we removed its row.
+ if (fFoundErrorVar)
+ {
+ ClVarSet &eVars = (*it_eVars).second;
+ ClVarSet::iterator it = eVars.begin();
+ for ( ; it != eVars.end(); ++it )
+ {
+ ClVariable v = (*it);
+ if (v != marker)
+ {
+ RemoveColumn(v);
+ }
+ }
+ }
+
+ if (pcn->isStayConstraint())
+ {
+ // iterate over the stay{Plus,Minus}ErrorVars and remove those
+ // variables v in those vectors that are also in set eVars
+ if (fFoundErrorVar)
+ {
+ ClVarSet &eVars = (*it_eVars).second;
+ _stayPlusErrorVars
+ .erase(remove_if(_stayPlusErrorVars.begin(),_stayPlusErrorVars.end(),
+ VarInVarSet(eVars)),
+ _stayPlusErrorVars.end());
+ _stayMinusErrorVars
+ .erase(remove_if(_stayMinusErrorVars.begin(),_stayMinusErrorVars.end(),
+ VarInVarSet(eVars)),
+ _stayMinusErrorVars.end());
+ }
+ }
+ else if (pcn->IsEditConstraint())
+ {
+ const ClEditConstraint *pcnEdit = dynamic_cast<const ClEditConstraint *>(pcn);
+ const ClVariable clv = pcnEdit->variable();
+ ClEditInfo *pcei = PEditInfoFromClv(clv);
+ assert(pcei);
+ ClVariable clvEditMinus = pcei->_clvEditMinus;
+ RemoveColumn(clvEditMinus); // clvEditPlus is a marker var and gets removed later
+ delete pcei;
+ _editInfoList.remove(pcei);
+ }
+
+ if (fFoundErrorVar)
+ {
+ // This code is not needed since the variables are deleted
+ // when they are removed from the row --
+ // leaving it in results in double deletions
+ // delete the constraint's error variables
+ // ClVarSet &evars_set = (*it_eVars).second;
+ // ClVarSet::const_iterator it_set = evars_set.begin();
+ // for ( ; it_set != evars_set.end(); ++it_set)
+ // {
+ // delete *it_set;
+ // }
+ _errorVars.erase((*it_eVars).first);
+ }
+
+ if (_fAutosolve)
+ {
+ Optimize(_objective);
+ SetExternalVariables();
+ }
+
+ return *this;
+}
+
+
+// Re-initialize this solver from the original constraints, thus
+// getting rid of any accumulated numerical problems. (Actually,
+// Alan hasn't observed any such problems yet, but here's the method
+// anyway.)
+void
+ClSimplexSolver::Reset()
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "()" << endl;
+#endif
+ // FIXGJB -- can postpone writing this for a while
+ // gotta be careful, though, as it's a likely place for
+ // a memory leak to sneak in
+ assert(false);
+}
+
+
+// Re-solve the cuurent collection of constraints, given the new
+// values for the edit variables that have already been
+// suggested (see SuggestValue() method)
+void
+ClSimplexSolver::Resolve()
+{ // CODE DUPLICATED ABOVE
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+#endif
+ DualOptimize();
+ SetExternalVariables();
+ _infeasibleRows.clear();
+ if (_fResetStayConstantsAutomatically)
+ ResetStayConstants();
+}
+
+ClSimplexSolver &
+ClSimplexSolver::SuggestValue(ClVariable v, Number x)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+#endif
+ ClEditInfo *pcei = PEditInfoFromClv(v);
+ if (NULL == pcei)
+ {
+#ifndef CL_NO_IO
+ std::stringstream ss;
+ ss << "SuggestValue for variable " << v << ", but var is not an edit variable" << ends;
+ throw ExCLEditMisuse(ss.str().c_str());
+#else
+ throw ExCLEditMisuse(v.Name().c_str());
+#endif
+ }
+ ClVariable clvEditPlus = pcei->_clvEditPlus;
+ ClVariable clvEditMinus = pcei->_clvEditMinus;
+ Number delta = x - pcei->_prevEditConstant;
+ pcei->_prevEditConstant = x;
+ DeltaEditConstant(delta,clvEditPlus,clvEditMinus);
+ return *this;
+}
+
+// Re-solve the cuurent collection of constraints, given the new
+// values for the edit variables that have already been
+// suggested (see SuggestValue() method)
+// This is not guaranteed to work if you remove an edit constraint
+// from the middle of the edit constraints you added
+// (e.g., edit A, edit B, edit C, remove B -> this will fail!)
+// DEPRECATED
+void
+ClSimplexSolver::Resolve(const vector<Number> &newEditConstants)
+{
+ ClEditInfoList::iterator it = _editInfoList.begin();
+ unsigned int i = 0;
+ for (; i < newEditConstants.size() && it != _editInfoList.end(); ++it, ++i)
+ {
+ ClEditInfo *pcei = (*it);
+ SuggestValue(pcei->_clv,newEditConstants[i]);
+ }
+ Resolve();
+}
+
+
+//// protected
+
+// Add the constraint expr=0 to the inequality tableau using an
+// artificial variable. To do this, create an artificial variable
+// av and Add av=expr to the inequality tableau, then make av be 0.
+// (Raise an exception if we can't attain av=0 -- and prepare explanation)
+bool
+ClSimplexSolver::AddWithArtificialVariable(ClLinearExpression &expr,
+ ExCLRequiredFailureWithExplanation &e)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << expr << ")" << endl;
+#endif
+
+ // Allocate the objects on the heap because the objects
+ // will remain in the tableau if we throw an exception,
+ // and that will result in the destructor cleaning up
+ // after us
+ ClSlackVariable *pav = new ClSlackVariable(++_artificialCounter,"a");
+ ClObjectiveVariable *paz = new ClObjectiveVariable("az");
+ ClLinearExpression *pazRow = new ClLinearExpression(expr);
+ // the artificial objective is av, which we know is equal to expr
+ // (which contains only parametric variables)
+
+#ifdef CL_FIND_LEAK
+ cerr << "aC = " << _artificialCounter
+ << "\nDeletes = " << _cArtificialVarsDeleted << endl;
+#endif
+#ifdef CL_TRACE
+ cerr << __FUNCTION__ << " before addRow-s:\n"
+ << (*this) << endl;
+#endif
+
+ // the artificial objective is av, which we know is equal to expr
+ // (which contains only parametric variables)
+
+ // objective is treated as a row in the tableau,
+ // so do the substitution for its value (we are minimizing
+ // the artificial variable)
+ // this row will be removed from the tableau after optimizing
+ addRow(*paz,*pazRow);
+
+ // now Add the normal row to the tableau -- when artifical
+ // variable is minimized to 0 (if possible)
+ // this row remains in the tableau to maintain the constraint
+ // we are trying to Add
+ addRow(*pav,expr);
+
+#ifdef CL_TRACE
+ cerr << __FUNCTION__ << " after addRow-s:\n"
+ << (*this) << endl;
+#endif
+
+ // try to Optimize az to 0
+ // note we are *not* optimizing the real objective, but optimizing
+ // the artificial objective to see if the error in the constraint
+ // we are adding can be set to 0
+ Optimize(*paz);
+
+ // Careful, we want to get the Expression that is in
+ // the tableau, not the one we initialized it with!
+ ClLinearExpression *pazTableauRow = RowExpression(*paz);
+#ifdef CL_TRACE
+ cerr << "pazTableauRow->Constant() == " << pazTableauRow->Constant() << endl;
+#endif
+
+ // Check that we were able to make the objective value 0
+ // If not, the original constraint was not satisfiable
+ if (!ClApprox(pazTableauRow->Constant(),0.0))
+ {
+ BuildExplanation(e, paz, pazTableauRow);
+ // remove the artificial objective row that we just
+ // added temporarily
+ delete RemoveRow(*paz);
+ // and delete the artificial objective variable that we also added above
+ delete paz;
+ return false;
+ }
+
+ // see if av is a basic variable
+ const ClLinearExpression *pe = RowExpression(*pav);
+ if (pe != NULL)
+ {
+ // FIXGJB: do we ever even get here?
+ // Find another variable in this row and Pivot, so that av becomes parametric
+ // If there isn't another variable in the row then
+ // the tableau contains the equation av = 0 -- just delete av's row
+ if (pe->IsConstant())
+ {
+ // FIXGJB: do we ever get here?
+ assert(ClApprox(pe->Constant(),0.0));
+ delete RemoveRow(*pav);
+ // remove the temporary objective function
+ // FIXGJB may need this too: delete RemoveRow(*paz);
+ delete pav;
+#ifdef CL_FIND_LEAK
+ ++_cArtificialVarsDeleted;
+#endif
+ return true;
+ }
+ ClVariable entryVar = pe->AnyPivotableVariable();
+ if (entryVar.IsNil())
+ {
+ BuildExplanation(e, *pav, pe);
+ return false; /* required failure */
+ }
+ Pivot(entryVar, *pav);
+ }
+ // now av should be parametric
+ assert(RowExpression(*pav) == NULL);
+ RemoveColumn(*pav);
+ delete pav;
+#ifdef CL_FIND_LEAK
+ ++_cArtificialVarsDeleted;
+#endif
+ // remove the temporary objective function
+ delete RemoveRow(*paz);
+ delete paz;
+ return true;
+}
+
+
+// Using the given equation (av = cle) build an explanation which
+// implicates all constraints used to construct the equation. That
+// is, everything for which the variables in the equation are markers.
+void ClSimplexSolver::BuildExplanation(ExCLRequiredFailureWithExplanation &e,
+ ClVariable av,
+ const ClLinearExpression *pcle)
+{
+ ClVarToConstraintMap::iterator it_cn;
+ it_cn = _constraintsMarked.find(av);
+ if (it_cn != _constraintsMarked.end())
+ {
+ e.AddConstraint((*it_cn).second);
+ }
+
+ assert(pcle != NULL);
+
+ const ClVarToNumberMap & terms = pcle->Terms();
+ ClVarToNumberMap::const_iterator it_term;
+ for (it_term = terms.begin(); it_term != terms.end(); it_term++)
+ {
+ it_cn = _constraintsMarked.find((*it_term).first);
+ if (it_cn != _constraintsMarked.end())
+ {
+ e.AddConstraint((*it_cn).second);
+ }
+ }
+}
+
+
+
+// We are trying to Add the constraint expr=0 to the appropriate
+// tableau. Try to Add expr directly to the tableaus without
+// creating an artificial variable. Return true if successful and
+// false if not.
+bool
+ClSimplexSolver::TryAddingDirectly(ClLinearExpression &expr)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << expr << ")" << endl;
+#endif
+ ClVariable subject = ChooseSubject(expr);
+ if (subject.get_pclv() == NULL )
+ {
+#ifdef CL_TRACE
+ cerr << "- returning false" << endl;
+#endif
+ return false;
+ }
+ expr.NewSubject(subject);
+ if (ColumnsHasKey(subject))
+ {
+ SubstituteOut(subject,expr);
+ }
+ addRow(subject,expr);
+#ifdef CL_TRACE
+ cerr << "- returning true" << endl;
+#endif
+ return true; // successfully added directly
+}
+
+
+// We are trying to Add the constraint expr=0 to the tableaux. Try
+// to choose a subject (a variable to become basic) from among the
+// current variables in expr. If expr contains any unrestricted
+// variables, then we must choose an unrestricted variable as the
+// subject. Also, if the subject is new to the solver we won't have
+// to do any substitutions, so we prefer new variables to ones that
+// are currently noted as parametric. If expr contains only
+// restricted variables, if there is a restricted variable with a
+// negative coefficient that is new to the solver we can make that
+// the subject. Otherwise we can't find a subject, so return nil.
+// (In this last case we have to Add an artificial variable and use
+// that variable as the subject -- this is done outside this method
+// though.)
+//
+// Note: in checking for variables that are new to the solver, we
+// ignore whether a variable occurs in the objective function, since
+// new slack variables are added to the objective function by
+// 'NewExpression:', which is called before this method.
+ClVariable
+ClSimplexSolver::ChooseSubject(ClLinearExpression &expr)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << expr << ")" << endl;
+#endif
+ ClVariable subject(clvNil); // the current best subject, if any
+
+ // true iff we have found a subject that is an unrestricted variable
+ bool foundUnrestricted = false;
+
+ // true iff we have found a restricted variable that is new to the
+ // solver (except for being in the obj. function) and that has a
+ // negative coefficient
+ bool foundNewRestricted = false;
+
+ const ClVarToNumberMap &terms = expr.Terms();
+ ClVarToNumberMap::const_iterator it = terms.begin();
+ for ( ; it != terms.end(); ++it )
+ {
+ ClVariable v = (*it).first;
+ Number c = (*it).second;
+
+ if (foundUnrestricted)
+ {
+ // We have already found an unrestricted variable. The only
+ // time we will want to use v instead of the current choice
+ // 'subject' is if v is unrestricted and new to the solver and
+ // 'subject' isn't new. If this is the case just pick v
+ // immediately and return.
+ if (!v.IsRestricted())
+ {
+ if (!ColumnsHasKey(v))
+ return v;
+ }
+ }
+ else
+ { // we haven't found an restricted variable yet
+ if (v.IsRestricted())
+ {
+ // v is restricted. If we have already found a suitable
+ // restricted variable just stick with that. Otherwise, if v
+ // is new to the solver and has a negative coefficient pick
+ // it. Regarding being new to the solver -- if the variable
+ // occurs only in the objective function we regard it as being
+ // new to the solver, since error variables are added to the
+ // objective function when we make the Expression. We also
+ // never pick a dummy variable here.
+ if (!foundNewRestricted && !v.IsDummy() && c < 0.0)
+ {
+ const ClTableauColumnsMap &col = Columns();
+ ClTableauColumnsMap::const_iterator it_col = col.find(v);
+ if (it_col == col.end() ||
+ ( col.size() == 1 && ColumnsHasKey(_objective) ) )
+ {
+ subject = v;
+ foundNewRestricted = true;
+ }
+ }
+ }
+ else
+ {
+ // v is unrestricted.
+ // If v is also new to the solver just pick it now
+ subject = v;
+ foundUnrestricted = true;
+ }
+ }
+ }
+ if (!subject.IsNil())
+ return subject;
+
+ // subject is nil.
+ // Make one last check -- if all of the variables in expr are dummy
+ // variables, then we can pick a dummy variable as the subject
+ Number coeff = 0;
+ it = terms.begin();
+ for ( ; it != terms.end(); ++it )
+ {
+ ClVariable v = (*it).first;
+ Number c = (*it).second;
+ if (!v.IsDummy())
+ return clvNil; // nope, no luck
+ // if v is new to the solver, tentatively make it the subject
+ if (!ColumnsHasKey(v))
+ {
+ subject = v;
+ coeff = c;
+ }
+ }
+
+ // If we get this far, all of the variables in the Expression should
+ // be dummy variables. If the Constant is nonzero we are trying to
+ // Add an unsatisfiable required constraint. (Remember that dummy
+ // variables must take on a value of 0.) Otherwise, if the Constant
+ // is Zero, multiply by -1 if necessary to make the coefficient for
+ // the subject negative."
+ if (!ClApprox(expr.Constant(),0.0))
+ {
+#ifdef CL_DEBUG_FAILURES
+ cerr << "required failure in choose subject:\n"
+ << *this << endl;
+#endif
+ if (FIsExplaining())
+ {
+ ExCLRequiredFailureWithExplanation e;
+ BuildExplanation(e, clvNil, &expr);
+ throw e;
+ }
+ else
+ throw ExCLRequiredFailure();
+ }
+ if (coeff > 0.0)
+ {
+ expr.MultiplyMe(-1);
+ }
+ return subject;
+}
+
+// Each of the non-required edits will be represented by an equation
+// of the form
+// v = c + eplus - eminus
+// where v is the variable with the edit, c is the previous edit
+// value, and eplus and eminus are slack variables that hold the
+// error in satisfying the edit constraint. We are about to change
+// something, and we want to fix the constants in the equations
+// representing the edit constraints. If one of eplus and eminus is
+// basic, the other must occur only in the Expression for that basic
+// error variable. (They can't both be basic.) Fix the Constant in
+// this Expression. Otherwise they are both nonbasic. Find all of
+// the expressions in which they occur, and fix the constants in
+// those. See the UIST paper for details.
+// (This comment was for resetEditConstants(), but that is now
+// gone since it was part of the screwey vector-based interface
+// to resolveing. --02/15/99 gjb)
+void
+ClSimplexSolver::DeltaEditConstant(Number delta,
+ ClVariable plusErrorVar,
+ ClVariable minusErrorVar)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << delta << ", " << plusErrorVar << ", " << minusErrorVar << ")" << endl;
+#endif
+ // first check if the plusErrorVar is basic
+ ClLinearExpression *pexprPlus = RowExpression(plusErrorVar);
+ if (pexprPlus != NULL )
+ {
+ pexprPlus->IncrementConstant(delta);
+ // error variables are always restricted
+ // so the row is infeasible if the Constant is negative
+ if (pexprPlus->Constant() < 0.0)
+ {
+ _infeasibleRows.insert(plusErrorVar);
+ }
+ return;
+ }
+ // check if minusErrorVar is basic
+ ClLinearExpression *pexprMinus = RowExpression(minusErrorVar);
+ if (pexprMinus != NULL)
+ {
+ pexprMinus->IncrementConstant(-delta);
+ if (pexprMinus->Constant() < 0.0)
+ {
+ _infeasibleRows.insert(minusErrorVar);
+ }
+ return;
+ }
+ // Neither is basic. So they must both be nonbasic, and will both
+ // occur in exactly the same expressions. Find all the expressions
+ // in which they occur by finding the column for the minusErrorVar
+ // (it doesn't matter whether we look for that one or for
+ // plusErrorVar). Fix the constants in these expressions.
+ ClVarSet &columnVars = _columns[minusErrorVar];
+ ClVarSet::iterator it = columnVars.begin();
+ for (; it != columnVars.end(); ++it)
+ {
+ ClVariable basicVar = *it;
+ ClLinearExpression *pexpr = RowExpression(basicVar);
+ assert(pexpr != NULL );
+ double c = pexpr->CoefficientFor(minusErrorVar);
+ pexpr->IncrementConstant(c*delta);
+ if (basicVar.IsRestricted() && pexpr->Constant() < 0.0)
+ {
+ _infeasibleRows.insert(basicVar);
+ }
+ }
+}
+
+// We have set new values for the constants in the edit constraints.
+// Re-Optimize using the dual simplex algorithm.
+void
+ClSimplexSolver::DualOptimize()
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "()" << endl;
+#endif
+ const ClLinearExpression *pzRow = RowExpression(_objective);
+ // need to handle infeasible rows
+ while (!_infeasibleRows.empty())
+ {
+ ClVarSet::iterator it_exitVar = _infeasibleRows.begin();
+ ClVariable exitVar = *it_exitVar;
+ _infeasibleRows.erase(it_exitVar);
+ ClVariable entryVar;
+ // exitVar might have become basic after some other pivoting
+ // so allow for the case of its not being there any longer
+ ClLinearExpression *pexpr = RowExpression(exitVar);
+ if (pexpr != NULL )
+ {
+ // make sure the row is still not feasible
+ if (pexpr->Constant() < 0.0)
+ {
+ double ratio = DBL_MAX;
+ double r;
+ ClVarToNumberMap &terms = pexpr->Terms();
+ ClVarToNumberMap::iterator it = terms.begin();
+ for ( ; it != terms.end(); ++it )
+ {
+ ClVariable v = (*it).first;
+ Number c = (*it).second;
+ if (c > 0.0 && v.IsPivotable())
+ {
+ Number zc = pzRow->CoefficientFor(v);
+ r = zc/c; // FIXGJB r:= zc/c or Zero, as ClSymbolicWeight-s
+ if (r < ratio)
+ {
+ entryVar = v;
+ ratio = r;
+ }
+ }
+ }
+ if (ratio == DBL_MAX)
+ {
+ stringstream ss;
+ ss << "ratio == nil (DBL_MAX)" << ends;
+ throw ExCLInternalError(ss.str().c_str());
+ }
+ Pivot(entryVar,exitVar);
+ }
+ }
+ }
+}
+
+// Make a new linear Expression representing the constraint cn,
+// replacing any basic variables with their defining expressions.
+// Normalize if necessary so that the Constant is non-negative. If
+// the constraint is non-required give its error variables an
+// appropriate weight in the objective function.
+ClLinearExpression *
+ClSimplexSolver::NewExpression(const ClConstraint *pcn,
+ /* output to */
+ ClVariable &clvEplus,
+ ClVariable &clvEminus,
+ Number &prevEConstant)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << *pcn << ")" << endl;
+ cerr << "cn.IsInequality() == " << pcn->IsInequality() << endl;
+ cerr << "cn.IsRequired() == " << pcn->IsRequired() << endl;
+#endif
+ const ClLinearExpression &cnExpr = pcn->Expression();
+ cl_auto_ptr<ClLinearExpression> pexpr ( new ClLinearExpression(cnExpr.Constant()) );
+ cl_auto_ptr<ClSlackVariable> pslackVar;
+ cl_auto_ptr<ClDummyVariable> pdummyVar;
+ cl_auto_ptr<ClSlackVariable> peminus(0);
+ cl_auto_ptr<ClSlackVariable> peplus(0);
+ const ClVarToNumberMap &cnTerms = cnExpr.Terms();
+ ClVarToNumberMap::const_iterator it = cnTerms.begin();
+ for ( ; it != cnTerms.end(); ++it)
+ {
+ ClVariable v = (*it).first;
+ Number c = (*it).second;
+ const ClLinearExpression *pe = RowExpression(v);
+ if (pe == NULL)
+ {
+ pexpr->AddVariable(v,c);
+ }
+ else
+ {
+ pexpr->AddExpression(*pe,c);
+ }
+ }
+
+ // Add slack and error variables as needed
+ if (pcn->IsInequality())
+ {
+ // cn is an inequality, so Add a slack variable. The original
+ // constraint is expr>=0, so that the resulting equality is
+ // expr-slackVar=0. If cn is also non-required Add a negative
+ // error variable, giving
+ // expr-slackVar = -errorVar, in other words
+ // expr-slackVar+errorVar=0.
+ // Since both of these variables are newly created we can just Add
+ // them to the Expression (they can't be basic).
+ ++_slackCounter;
+ ReinitializeAutoPtr(pslackVar,new ClSlackVariable (_slackCounter, "s"));
+ pexpr->setVariable(*pslackVar,-1);
+ // index the constraint under its slack variable and vice-versa
+ _markerVars[pcn] = pslackVar.get();
+ _constraintsMarked[pslackVar.get()] = pcn;
+
+ if (!pcn->IsRequired())
+ {
+ ++_slackCounter;
+ ReinitializeAutoPtr(peminus,new ClSlackVariable (_slackCounter, "em"));
+ pexpr->setVariable(*peminus,1.0);
+ // Add emnius to the objective function with the appropriate weight
+ ClLinearExpression *pzRow = RowExpression(_objective);
+ // FIXGJB: pzRow->AddVariable(eminus,pcn->strength().symbolicWeight() * pcn->weight());
+ ClSymbolicWeight sw = pcn->strength().symbolicWeight().Times(pcn->weight());
+ pzRow->setVariable(*peminus,sw.AsDouble());
+ _errorVars[pcn].insert(peminus.get());
+ NoteAddedVariable(*peminus,_objective);
+ }
+ }
+ else
+ { // cn is an equality
+ if (pcn->IsRequired())
+ {
+ // Add a dummy variable to the Expression to serve as a marker
+ // for this constraint. The dummy variable is never allowed to
+ // enter the basis when pivoting.
+ ++_dummyCounter;
+ ReinitializeAutoPtr(pdummyVar,new ClDummyVariable (_dummyCounter, "d"));
+ pexpr->setVariable(*pdummyVar,1.0);
+ _markerVars[pcn] = pdummyVar.get();
+ _constraintsMarked[pdummyVar.get()] = pcn;
+#ifdef CL_TRACE
+ cerr << "Adding dummyVar == d" << _dummyCounter << endl;
+#endif
+ }
+ else
+ {
+ // cn is a non-required equality. Add a positive and a negative
+ // error variable, making the resulting constraint
+ // expr = eplus - eminus,
+ // in other words: expr-eplus+eminus=0
+ ++_slackCounter;
+ ReinitializeAutoPtr(peplus,new ClSlackVariable (_slackCounter, "ep"));
+ ReinitializeAutoPtr(peminus,new ClSlackVariable (_slackCounter, "em"));
+
+ pexpr->setVariable(*peplus,-1.0);
+ pexpr->setVariable(*peminus,1.0);
+ // index the constraint under one of the error variables
+ _markerVars[pcn] = peplus.get();
+ _constraintsMarked[peplus.get()] = pcn;
+
+ ClLinearExpression *pzRow = RowExpression(_objective);
+ // FIXGJB: pzRow->AddVariable(eplus,pcn->strength().symbolicWeight() * pcn->weight());
+ ClSymbolicWeight sw = pcn->strength().symbolicWeight().Times(pcn->weight());
+ double swCoeff = sw.AsDouble();
+#ifdef CL_TRACE
+ if (swCoeff == 0)
+ {
+ cerr << "sw == " << sw << endl
+ << "cn == " << *pcn << endl;
+ cerr << "adding " << *peplus << " and " << *peminus
+ << " with swCoeff == " << swCoeff << endl;
+ }
+#endif
+ pzRow->setVariable(*peplus,swCoeff);
+ NoteAddedVariable(*peplus,_objective);
+ // FIXGJB: pzRow->AddVariable(eminus,pcn->strength().symbolicWeight() * pcn->weight());
+ pzRow->setVariable(*peminus,swCoeff);
+ NoteAddedVariable(*peminus,_objective);
+ _errorVars[pcn].insert(peminus.get());
+ _errorVars[pcn].insert(peplus.get());
+ if (pcn->isStayConstraint())
+ {
+ _stayPlusErrorVars.push_back(peplus.get());
+ _stayMinusErrorVars.push_back(peminus.get());
+ }
+ else if (pcn->IsEditConstraint())
+ {
+ clvEplus = peplus.get();
+ clvEminus = peminus.get();
+ prevEConstant = cnExpr.Constant();
+ }
+ }
+ }
+
+ // the Constant in the Expression should be non-negative.
+ // If necessary normalize the Expression by multiplying by -1
+ if (pexpr->Constant() < 0)
+ {
+#ifdef CL_TRACE
+ cerr << "NewExpression's Constant is " << pexpr->Constant() << ", < 0, so flipping" << endl;
+#endif
+ pexpr->MultiplyMe(-1);
+ }
+#ifdef CL_TRACE
+ cerr << "- returning " << *pexpr << endl;
+#endif
+ // Terrible Name -- release() does *not* delete the object,
+ // only makes sure that the destructor won't delete the object
+ // (it releases the cl_auto_ptr from the responsibility of deleting the object)
+ pslackVar.release();
+ pdummyVar.release();
+ peminus.release();
+ peplus.release();
+ return pexpr.release();
+}
+
+// Minimize the value of the objective. (The tableau should already
+// be feasible.)
+void
+ClSimplexSolver::Optimize(ClVariable zVar)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << zVar << ")\n"
+ << *this << endl;
+#endif
+ ClLinearExpression *pzRow = RowExpression(zVar);
+ assert(pzRow != NULL);
+ ClVariable entryVar = clvNil;
+ ClVariable exitVar = clvNil;
+ while (true)
+ {
+ Number objectiveCoeff = 0;
+ // Find the most negative coefficient in the objective function
+ // (ignoring the non-pivotable dummy variables). If all
+ // coefficients are positive we're done
+ ClVarToNumberMap &terms = pzRow->Terms();
+ ClVarToNumberMap::iterator it = terms.begin();
+ for (; it != terms.end(); ++it)
+ {
+ ClVariable v = (*it).first;
+ Number c = (*it).second;
+ if (v.IsPivotable() && c < objectiveCoeff)
+ {
+ objectiveCoeff = c;
+ entryVar = v;
+ // A. Beurive' Tue Jul 13 23:03:05 CEST 1999 Why the most
+ // negative? I encountered unending cycles of pivots!
+ break;
+ }
+ }
+ // if all coefficients were positive (or if the objective
+ // function has no pivotable variables)
+ // we are at an optimum
+ if (objectiveCoeff >= -_epsilon)
+ return;
+#ifdef CL_TRACE
+ cerr << "entryVar == " << entryVar << ", "
+ << "objectiveCoeff == " << objectiveCoeff
+ << endl;
+#endif
+
+ // choose which variable to move out of the basis
+ // Only consider pivotable basic variables
+ // (i.e. restricted, non-dummy variables)
+ double minRatio = DBL_MAX;
+ ClVarSet &columnVars = _columns[entryVar];
+ ClVarSet::iterator it_rowvars = columnVars.begin();
+ Number r = 0.0;
+ for (; it_rowvars != columnVars.end(); ++it_rowvars)
+ {
+ ClVariable v = *it_rowvars;
+#ifdef CL_TRACE
+ cerr << "Checking " << v << endl;
+#endif
+ if (v.IsPivotable())
+ {
+ const ClLinearExpression *pexpr = RowExpression(v);
+ Number coeff = pexpr->CoefficientFor(entryVar);
+ // only consider negative coefficients
+ if (coeff < 0.0)
+ {
+ r = - pexpr->Constant() / coeff;
+ if (r < minRatio)
+ {
+#ifdef CL_TRACE
+ cerr << "New minRatio == " << r << endl;
+#endif
+ minRatio = r;
+ exitVar = v;
+ }
+ }
+ }
+ }
+ // If minRatio is still nil at this point, it means that the
+ // objective function is unbounded, i.e. it can become
+ // arbitrarily negative. This should never happen in this
+ // application.
+ if (minRatio == DBL_MAX)
+ {
+ stringstream ss;
+ ss << "objective function is unbounded!" << ends;
+ throw ExCLInternalError(ss.str().c_str());
+ }
+ Pivot(entryVar, exitVar);
+#ifdef CL_TRACE
+ cerr << "After Optimize:\n"
+ << *this << endl;
+#endif
+ }
+}
+
+// Do a Pivot. Move entryVar into the basis (i.e. make it a basic variable),
+// and move exitVar out of the basis (i.e., make it a parametric variable)
+void
+ClSimplexSolver::Pivot(ClVariable entryVar, ClVariable exitVar)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << entryVar << ", " << exitVar << ")" << endl;
+#endif
+
+ // the entryVar might be non-pivotable if we're doing a RemoveConstraint --
+ // otherwise it should be a pivotable variable -- enforced at call sites,
+ // hopefully
+
+ // expr is the Expression for the exit variable (about to leave the basis) --
+ // so that the old tableau includes the equation:
+ // exitVar = expr
+ ClLinearExpression *pexpr = RemoveRow(exitVar);
+
+ // Compute an Expression for the entry variable. Since expr has
+ // been deleted from the tableau we can destructively modify it to
+ // build this Expression.
+ pexpr->ChangeSubject(exitVar,entryVar);
+ SubstituteOut(entryVar,*pexpr);
+
+ if (entryVar.IsExternal())
+ {
+ // entry var is no longer a parametric variable since we're moving
+ // it into the basis
+ _externalParametricVars.erase(entryVar);
+ }
+ addRow(entryVar,*pexpr);
+}
+
+
+
+// Each of the non-required stays will be represented by an equation
+// of the form
+// v = c + eplus - eminus
+// where v is the variable with the stay, c is the previous value of
+// v, and eplus and eminus are slack variables that hold the error
+// in satisfying the stay constraint. We are about to change
+// something, and we want to fix the constants in the equations
+// representing the stays. If both eplus and eminus are nonbasic
+// they have value 0 in the current solution, meaning the previous
+// stay was exactly satisfied. In this case nothing needs to be
+// changed. Otherwise one of them is basic, and the other must
+// occur only in the Expression for that basic error variable.
+// Reset the Constant in this Expression to 0.
+void
+ClSimplexSolver::ResetStayConstants()
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "()" << endl;
+#endif
+ ClVarVector::const_iterator
+ itStayPlusErrorVars = _stayPlusErrorVars.begin();
+ ClVarVector::const_iterator
+ itStayMinusErrorVars = _stayMinusErrorVars.begin();
+
+ for ( ; itStayPlusErrorVars != _stayPlusErrorVars.end();
+ ++itStayPlusErrorVars, ++itStayMinusErrorVars )
+ {
+ ClLinearExpression *pexpr = RowExpression(*itStayPlusErrorVars);
+ if (pexpr == NULL )
+ {
+ pexpr = RowExpression(*itStayMinusErrorVars);
+ }
+ if (pexpr != NULL)
+ {
+ pexpr->Set_constant(0.0);
+ }
+ }
+}
+
+// Set the external variables known to this solver to their appropriate values.
+// Set each external basic variable to its value, and set each
+// external parametric variable to 0. (It isn't clear that we will
+// ever have external parametric variables -- every external
+// variable should either have a stay on it, or have an equation
+// that defines it in terms of other external variables that do have
+// stays. For the moment I'll put this in though.) Variables that
+// are internal to the solver don't actually store values -- their
+// values are just implicit in the tableu -- so we don't need to set
+// them."
+void
+ClSimplexSolver::SetExternalVariables()
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "()\n"
+ << *this << endl;
+#endif
+
+ // FIXGJB -- oughta check some invariants here
+
+ // Set external parametric variables first
+ // in case I've screwed up
+ ClVarSet::iterator itParVars = _externalParametricVars.begin();
+ for ( ; itParVars != _externalParametricVars.end(); ++itParVars )
+ {
+ ClVariable v = *itParVars;
+#ifndef NDEBUG
+ // defensively skip it if it is basic -- ChangeValue is virtual
+ // so don't want to call it twice; this should never
+ // happen
+ if (FIsBasicVar(v))
+ {
+#ifndef CL_NO_IO
+ // WARNING
+ cerr << __FUNCTION__ << "Error: variable " << v
+ << " in _externalParametricVars is basic" << endl;
+ cerr << "Row is: " << *RowExpression(v) << endl;
+#endif
+ continue;
+ }
+#endif
+ ChangeClv(v,0.0);
+ }
+
+ // Only iterate over the rows w/ external variables
+ ClVarSet::iterator itRowVars = _externalRows.begin();
+ for ( ; itRowVars != _externalRows.end() ; ++itRowVars )
+ {
+ ClVariable v = *itRowVars;
+ ClLinearExpression *pexpr = RowExpression(v);
+ ChangeClv(v,pexpr->Constant());
+ }
+
+ _fNeedsSolving = false;
+ if (_pfnResolveCallback)
+ _pfnResolveCallback(this);
+}
+
+#ifndef CL_NO_IO
+ostream &
+PrintTo(ostream &xo, const ClVarVector &varlist)
+{
+ ClVarVector::const_iterator it = varlist.begin();
+ xo << varlist.size() << ":" << "[ ";
+ if (it != varlist.end())
+ {
+ xo << *it;
+ ++it;
+ }
+ for (; it != varlist.end(); ++it)
+ {
+ xo << ", " << *it;
+ }
+ xo << " ]";
+ return xo;
+}
+
+ostream &operator<<(ostream &xo, const ClVarVector &varlist)
+{ return PrintTo(xo,varlist); }
+
+
+ostream &
+PrintTo(ostream &xo, const ClConstraintToVarSetMap &mapCnToVarSet)
+{
+ ClConstraintToVarSetMap::const_iterator it = mapCnToVarSet.begin();
+ for ( ; it != mapCnToVarSet.end(); ++it) {
+ const ClConstraint *pcn = (*it).first;
+ const ClVarSet &set = (*it).second;
+ xo << "CN: " << pcn << *pcn << ":: " << set << endl;
+ }
+ return xo;
+}
+
+ostream &operator <<(ostream &xo, const ClConstraintToVarSetMap &mapCnToVarSet)
+{ return PrintTo(xo,mapCnToVarSet); }
+
+
+
+ostream &
+ClSimplexSolver::PrintOn(ostream &xo) const
+{
+ ClTableau::PrintOn(xo);
+
+ xo << "_stayPlusErrorVars: "
+ << _stayPlusErrorVars << endl;
+ xo << "_stayMinusErrorVars: "
+ << _stayMinusErrorVars << endl;
+ xo << "_editInfoList:\n"
+ << _editInfoList << endl;
+ return xo;
+}
+
+
+ostream &
+ClSimplexSolver::PrintInternalInfo(ostream &xo) const
+{
+ ClTableau::PrintInternalInfo(xo);
+ xo << "; edvars: " << _editInfoList.size();
+ xo << endl;
+ printExternalVariablesTo(xo);
+ return xo;
+}
+
+ostream &operator<<(ostream &xo, const ClSimplexSolver &clss)
+{
+ return clss.PrintOn(xo);
+}
+
+#endif
+
+bool
+ClSimplexSolver::FIsConstraintSatisfied(const ClConstraint *const pcn) const
+{
+ ClConstraintToVarMap::const_iterator it_marker = _markerVars.find(pcn);
+ if (it_marker == _markerVars.end())
+ { // could not find the constraint
+ throw ExCLConstraintNotFound();
+ }
+
+#ifndef CL_NO_IO
+ bool fCnsays = pcn->FIsSatisfied();
+#endif
+
+ ClConstraintToVarSetMap::const_iterator it_eVars = _errorVars.find(pcn);
+
+ if (it_eVars != _errorVars.end())
+ {
+ const ClVarSet &eVars = (*it_eVars).second;
+ ClVarSet::const_iterator it = eVars.begin();
+ for ( ; it != eVars.end(); ++it )
+ {
+ const ClLinearExpression *pexpr = RowExpression(*it);
+ if (pexpr != NULL && !ClApprox(pexpr->Constant(),0.0))
+ {
+#ifndef CL_NO_IO
+ if (fCnsays)
+ cerr << __FUNCTION__ << ": constraint says satisfiable, but solver does not" << endl;
+#endif
+ return false;
+ }
+ }
+ }
+
+#ifndef CL_NO_IO
+ if (!fCnsays)
+ cerr << __FUNCTION__ << ": solver says satisfiable, but constraint does not" << endl;
+#endif
+ return true;
+}
+
+
+
+#ifndef CL_NO_ID
+
+ostream &PrintTo(ostream &xo, const ClSimplexSolver::ClEditInfoList &listPEditInfo)
+{
+ ClSimplexSolver::ClEditInfoList::const_iterator it = listPEditInfo.begin();
+ for ( ; it != listPEditInfo.end(); ++it) {
+ const ClSimplexSolver::ClEditInfo *pcei = (*it);
+ xo << *pcei << endl;
+ }
+ return xo;
+}
+
+
+ostream &operator<<(ostream &xo, const ClSimplexSolver::ClEditInfoList &listPEditInfo)
+{ return PrintTo(xo,listPEditInfo); }
+
+#endif
+
+// A. Beurive' Tue Jul 6 17:03:32 CEST 1999
+void
+ClSimplexSolver::ChangeStrengthAndWeight(ClConstraint *pcn, const ClStrength &strength, double weight)
+{
+ ClConstraintToVarSetMap::iterator it_eVars = _errorVars.find(pcn);
+ // Only for constraints that already have error variables (i.e. non-required constraints)
+ assert(it_eVars != _errorVars.end());
+
+ ClLinearExpression *pzRow = RowExpression(_objective);
+
+ Number old_coeff = pcn->weight() * pcn->strength().symbolicWeight().AsDouble();
+ pcn->setStrength(strength);
+ pcn->setWeight(weight);
+ Number new_coeff = pcn->weight() * pcn->strength().symbolicWeight().AsDouble();
+
+ if (new_coeff != old_coeff)
+ {
+#ifdef CL_TRACE
+ cerr << "Changing strength and/or weight for constraint: " << endl << *pcn << endl;
+ cerr << "Updating objective row from:" << endl << *pzRow << endl;
+#endif
+ ClVarSet &eVars = (*it_eVars).second;
+ ClVarSet::iterator it = eVars.begin();
+ for ( ; it != eVars.end(); ++it )
+ {
+ const ClLinearExpression *pexpr = RowExpression(*it);
+ if (pexpr == NULL )
+ {
+ pzRow->AddVariable(*it,-old_coeff,_objective,*this);
+ pzRow->AddVariable(*it,new_coeff,_objective,*this);
+ }
+ else
+ {
+ pzRow->AddExpression(*pexpr,-old_coeff,_objective,*this);
+ pzRow->AddExpression(*pexpr,new_coeff,_objective,*this);
+ }
+ }
+#ifdef CL_TRACE
+ cerr << "to: " << endl << *pzRow << endl;
+#endif
+
+ if (_fAutosolve)
+ {
+ Optimize(_objective);
+ SetExternalVariables();
+ }
+ }
+}
+
+// A. Beurive' Tue Jul 6 17:03:42 CEST 1999
+void
+ClSimplexSolver::ChangeStrength(ClConstraint *pcn, const ClStrength &strength)
+{
+ ChangeStrengthAndWeight(pcn,strength,pcn->weight());
+}
+
+// A. Beurive' Tue Jul 6 17:03:42 CEST 1999
+void
+ClSimplexSolver::ChangeWeight(ClConstraint *pcn, double weight)
+{
+ ChangeStrengthAndWeight(pcn,pcn->strength(),weight);
+}
diff --git a/libs/cassowary/ClSlackVariable.cc b/libs/cassowary/ClSlackVariable.cc
new file mode 100644
index 0000000000..eaf0432eb0
--- /dev/null
+++ b/libs/cassowary/ClSlackVariable.cc
@@ -0,0 +1,12 @@
+// $Id$
+
+#include <cassowary/ClSlackVariable.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+#ifdef CL_FIND_LEAK
+long ClSlackVariable::cSlackVariables = 0;
+#endif
diff --git a/libs/cassowary/ClSolver.cc b/libs/cassowary/ClSolver.cc
new file mode 100644
index 0000000000..18b0b7f9cc
--- /dev/null
+++ b/libs/cassowary/ClSolver.cc
@@ -0,0 +1,59 @@
+// $Id$
+
+using namespace std;
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+#include <cassowary/Cassowary.h>
+#include <cassowary/ClSolver.h>
+#include <cassowary/ClConstraint.h>
+#include <cassowary/ClErrors.h>
+#include <cassowary/ClTypedefs.h>
+
+
+ClSolver &
+ClSolver::AddConstraint(ClConstraint *const )
+{
+ return *this;
+}
+
+
+ostream &
+PrintTo(ostream &xo, const ClConstraintSet &setCn)
+{
+ ClConstraintSet::const_iterator it = setCn.begin();
+ for (; it != setCn.end(); ++it) {
+ const ClConstraint *pcn = *it;
+ xo << *pcn << endl;
+ }
+ return xo;
+}
+
+ostream &
+PrintTo(ostream &xo, const list<FDNumber> &listFDN)
+{
+ list<FDNumber>::const_iterator it = listFDN.begin();
+ for (; it != listFDN.end(); ) {
+ FDNumber n = *it;
+ xo << n;
+ ++it;
+ if (it != listFDN.end())
+ xo << ",";
+ }
+ return xo;
+}
+
+
+ostream &operator<<(ostream &xo, const ClConstraintSet &setCn)
+{ return PrintTo(xo,setCn); }
+
+
+ostream &operator<<(ostream &xo, const ClSolver &solver)
+{ return solver.PrintOn(xo); }
+
+ostream &operator<<(ostream &xo, const list<FDNumber> &listFDN)
+{ return PrintTo(xo,listFDN); }
+
diff --git a/libs/cassowary/ClStrength.cc b/libs/cassowary/ClStrength.cc
new file mode 100644
index 0000000000..0629d4afff
--- /dev/null
+++ b/libs/cassowary/ClStrength.cc
@@ -0,0 +1,52 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClStrength.cc
+
+#include <cassowary/ClStrength.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+// Use the singleton pattern for the strength objects
+const ClStrength &ClsRequired()
+{
+ // required is distinct by equality to this static object,
+ // but I still use an especially high symbolic weight, just in case
+ // FIXGJB: hack?
+ static ClStrength required_strength("<Required>", 1000, 1000, 1000);
+ return required_strength;
+}
+
+const ClStrength &ClsStrong()
+{
+ static ClStrength strong_strength("strong", 1.0, 0.0, 0.0);
+ return strong_strength;
+}
+
+const ClStrength &ClsMedium()
+{
+ static ClStrength medium_strength("medium", 0.0, 1.0, 0.0);
+ return medium_strength;
+}
+
+
+const ClStrength &ClsWeak()
+{
+ static ClStrength weak_strength("weak", 0.0, 0.0, 1.0);
+ return weak_strength;
+}
+
+// special case for when nLevels = 3, should assert nLevels() == 3
+ClStrength::ClStrength(const string &Name, double w1, double w2, double w3) :
+ _name(Name), _symbolicWeight(w1, w2, w3)
+{
+}
diff --git a/libs/cassowary/ClSymbolicWeight.cc b/libs/cassowary/ClSymbolicWeight.cc
new file mode 100644
index 0000000000..9dddaa5949
--- /dev/null
+++ b/libs/cassowary/ClSymbolicWeight.cc
@@ -0,0 +1,149 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClSymbolicWeight.cc
+
+#include <cassowary/Cassowary.h>
+#include <cassowary/ClSymbolicWeight.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+// Help g++ out, tell it to instantiate this
+//template vector<double> &vector<double>::operator =(const vector<double> &);
+
+ClSymbolicWeight::ClSymbolicWeight(unsigned int CLevels, double value) :
+ _values(CLevels, value)
+{
+ assert(_values.size() == CLevels);
+}
+
+ClSymbolicWeight::ClSymbolicWeight(double w1, double w2, double w3)
+{
+ _values.push_back(w1);
+ _values.push_back(w2);
+ _values.push_back(w3);
+ assert(_values.size() == 3);
+}
+
+ClSymbolicWeight::ClSymbolicWeight(const vector<double> &weights) :
+ _values(weights)
+{ }
+
+ClSymbolicWeight &
+ClSymbolicWeight::Zero()
+{
+ static ClSymbolicWeight Zero(0.0, 0.0, 0.0);
+ return Zero;
+}
+
+
+ClSymbolicWeight &
+ClSymbolicWeight::negated()
+{
+ vector<double>::iterator it = _values.begin();
+ for (; it != _values.end(); ++it)
+ {
+ *it = -*it;
+ }
+ return *this;
+}
+
+ClSymbolicWeight &
+ClSymbolicWeight::MultiplyMe(Number n)
+{
+ vector<double>::iterator it = _values.begin();
+ for (; it != _values.end(); ++it)
+ {
+ *it *= n;
+ }
+ return *this;
+}
+
+
+ClSymbolicWeight
+ClSymbolicWeight::DivideBy(Number n) const
+{
+ assert(n!=0);
+ ClSymbolicWeight clsw(0);
+ vector<double>::const_iterator i = _values.begin();
+ for (; i != _values.end(); ++i)
+ {
+ clsw.push_back(*i / n);
+ }
+ return clsw;
+}
+
+ClSymbolicWeight &
+ClSymbolicWeight::addtoMe(const ClSymbolicWeight &cl)
+{
+ assert(cl.CLevels() == CLevels());
+
+ vector<double>::iterator i1 = _values.begin();
+ vector<double>::const_iterator i2 = cl._values.begin();
+ for (; i1 != _values.end(); ++i1, ++i2)
+ {
+ *i1 += *i2;
+ }
+ return *this;
+}
+
+ClSymbolicWeight
+ClSymbolicWeight::Subtract(const ClSymbolicWeight &cl) const
+{
+ assert(cl.CLevels() == CLevels());
+
+ ClSymbolicWeight clsw(0);
+ vector<double>::const_iterator i1 = _values.begin();
+ vector<double>::const_iterator i2 = cl._values.begin();
+ for (; i1 != _values.end(); ++i1, ++i2)
+ {
+ clsw.push_back(*i1 - *i2);
+ }
+ return clsw;
+}
+
+
+bool
+ClSymbolicWeight::lessThan(const ClSymbolicWeight &cl) const
+{
+ return _values < cl._values;
+}
+
+bool
+ClSymbolicWeight::lessThanOrEqual(const ClSymbolicWeight &cl) const
+{
+ return _values <= cl._values;
+}
+
+bool
+ClSymbolicWeight::equal(const ClSymbolicWeight &cl) const
+{
+ return _values == cl._values;
+}
+
+bool
+ClSymbolicWeight::greaterThan(const ClSymbolicWeight &cl) const
+{
+ return _values > cl._values;
+}
+
+bool
+ClSymbolicWeight::greaterThanOrEqual(const ClSymbolicWeight &cl) const
+{
+ return _values >= cl._values;
+}
+
+bool
+ClSymbolicWeight::isNegative() const
+{
+ return _values < Zero()._values;
+}
diff --git a/libs/cassowary/ClTableau.cc b/libs/cassowary/ClTableau.cc
new file mode 100644
index 0000000000..85ac841725
--- /dev/null
+++ b/libs/cassowary/ClTableau.cc
@@ -0,0 +1,297 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClTableau.cc
+
+using namespace std;
+
+#include <cassowary/ClTableau.h>
+#include <cassowary/debug.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+
+// delete the linear expressions
+// let ClSimplexSolver worry about deleting the variables
+ClTableau::~ClTableau()
+{
+ ClTableauRowsMap::iterator it = _rows.begin();
+ for (; it != _rows.end(); ++it)
+ {
+ // free the ClLinearExpression that we new-ed
+#ifdef CL_TRACE
+ cerr << "Deleting row delete@ " << ((*it).second) << endl;
+#endif
+ delete (*it).second;
+ }
+}
+
+#ifndef CL_NO_IO
+// Some extra debugging info
+ostream &
+ClTableau::PrintInternalInfo(ostream &xo) const
+{
+ xo << "ncns:" << _rows.size() -1
+ << "; cols:" << _columns.size()
+ << "; infrows:" << _infeasibleRows.size()
+ << "; ebvars:" << _externalRows.size()
+ << "; epvars:" << _externalParametricVars.size();
+ return xo;
+}
+
+
+ostream &
+ClTableau::printExternalVariablesTo(ostream &xo) const
+{
+ xo << "Parametric: ";
+ ClVarSet::iterator itParVars = _externalParametricVars.begin();
+ for ( ; itParVars != _externalParametricVars.end(); ++itParVars ) {
+ ClVariable v = *itParVars;
+ xo << v << " ";
+ }
+ xo << "\nBasic: ";
+ ClVarSet::iterator itRowVars = _externalRows.begin();
+ for ( ; itRowVars != _externalRows.end() ; ++itRowVars ) {
+ ClVariable v = *itRowVars;
+ xo << v << " ";
+ }
+ return xo << endl;
+}
+
+#endif
+
+
+// Add v, update column cross indices
+// v becomes a basic variable
+// expr is now owned by ClTableau class,
+// and ClTableauis responsible for deleting it
+// (also, expr better be allocated on the heap!)
+void
+ClTableau::addRow(ClVariable var, const ClLinearExpression &expr)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << var << ", " << expr << ")" << endl;
+#endif
+ _rows[var] = const_cast<ClLinearExpression *>(&expr);
+ ClVarToNumberMap::const_iterator it = expr.Terms().begin();
+ // for each variable in expr, Add var to the set of rows which have that variable
+ // in their Expression
+ for (; it != expr.Terms().end(); ++it)
+ {
+ ClVariable v = (*it).first;
+ _columns[v].insert(var);
+ if (v.IsExternal() && !FIsBasicVar(v))
+ {
+ _externalParametricVars.insert(v);
+ }
+ }
+ if (var.IsExternal())
+ {
+ _externalRows.insert(var);
+ }
+#ifdef CL_TRACE
+ cerr << *this << endl;
+#endif
+}
+
+// Remove var from the tableau -- remove the column cross indices for var
+// and remove var from every Expression in rows in which v occurs
+// Remove the parametric variable var, updating the appropriate column and row entries.
+// (Renamed from Smalltalk implementation's `removeParametricVar')
+ClVariable
+ClTableau::RemoveColumn(ClVariable var)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << var << ")" << endl;
+#endif
+ ClTableauColumnsMap::iterator it_var = _columns.find(var);
+ if (it_var == _columns.end())
+ return var; // nothing to do
+
+ ClVarSet &varset = (*it_var).second;
+ // remove the rows with the variables in varset
+ ClVarSet::iterator it = varset.begin();
+ for (; it != varset.end(); ++it)
+ {
+ ClVariable v = (*it);
+ ClVarToNumberMap &Terms = _rows[v]->Terms();
+ Terms.erase(Terms.find(var));
+ }
+ if (var.IsExternal())
+ {
+ _externalRows.erase(var);
+ _externalParametricVars.erase(var);
+ }
+ _columns.erase(it_var);
+ return var;
+}
+
+// Remove the basic variable v from the tableau row v=expr
+// Then update column cross indices
+ClLinearExpression *
+ClTableau::RemoveRow(ClVariable var)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << var << ")" << endl;
+#endif
+ ClTableauRowsMap::iterator it = _rows.find(var);
+ assert(it != _rows.end());
+ ClLinearExpression *pexpr = (*it).second;
+ ClVarToNumberMap &Terms = pexpr->Terms();
+ ClVarToNumberMap::iterator it_term = Terms.begin();
+ for (; it_term != Terms.end(); ++it_term)
+ {
+ ClVariable v = (*it_term).first;
+ _columns[v].erase(var);
+ if (_columns[v].size() == 0)
+ {
+ _columns.erase(v);
+ _externalParametricVars.erase(v);
+ }
+ }
+
+ _infeasibleRows.erase(var);
+
+ if (var.IsExternal())
+ {
+ _externalRows.erase(var);
+ _externalParametricVars.erase(var);
+ }
+
+ _rows.erase(it);
+#ifdef CL_TRACE
+ cerr << "- returning " << *pexpr << endl;
+#endif
+ return pexpr;
+}
+
+// Replace all occurrences of oldVar with expr, and update column cross indices
+// oldVar should now be a basic variable
+// Uses the Columns data structure and calls SubstituteOut on each
+// row that has oldVar in it
+// oldVar is leaving the basis, and becoming parametric
+void
+ClTableau::SubstituteOut(ClVariable oldVar, const ClLinearExpression &expr)
+{
+#ifdef CL_TRACE
+ cerr << "* ClTableau::";
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << oldVar << ", " << expr << ")" << endl;
+ cerr << (*this) << endl;
+#endif
+
+ ClTableauColumnsMap::iterator it_oldVar = _columns.find(oldVar);
+ if (it_oldVar == _columns.end())
+ return;
+
+ ClVarSet &varset = (*it_oldVar).second;
+ ClVarSet::iterator it = varset.begin();
+ for (; it != varset.end(); ++it)
+ {
+ ClVariable v = (*it);
+ ClLinearExpression *prow = _rows[v];
+ prow->SubstituteOut(oldVar,expr,v,*this);
+ if (v.IsRestricted() && prow->Constant() < 0.0)
+ {
+ _infeasibleRows.insert(v);
+ }
+ }
+ _columns.erase(it_oldVar);
+ if (oldVar.IsExternal())
+ {
+ if (_columns[oldVar].size() > 0)
+ {
+ _externalRows.insert(oldVar);
+ }
+ _externalParametricVars.erase(oldVar);
+ }
+}
+
+
+#ifndef CL_NO_IO
+
+ostream &
+PrintTo(ostream &xo, const ClVarSet & varset)
+{
+ ClVarSet::const_iterator it = varset.begin();
+ xo << "{ ";
+ if (it != varset.end())
+ {
+ xo << *it;
+ ++it;
+ }
+ for (; it != varset.end(); ++it)
+ {
+ xo << ", " << *it;
+ }
+ xo << " }";
+ return xo;
+}
+
+ostream &operator<<(ostream &xo, const ClVarSet & varset)
+{ return PrintTo(xo,varset); }
+
+ostream &
+PrintTo(ostream &xo, const ClTableauColumnsMap & varmap)
+{
+ ClTableauColumnsMap::const_iterator it = varmap.begin();
+ for (; it != varmap.end(); ++it)
+ {
+ xo << (*it).first << " -> " << (*it).second << endl;
+ }
+ return xo;
+}
+
+ostream &operator<<(ostream &xo, const ClTableauColumnsMap & varmap)
+{ return PrintTo(xo,varmap); }
+
+ostream &
+PrintTo(ostream &xo, const ClTableauRowsMap & rows)
+{
+ ClTableauRowsMap::const_iterator it = rows.begin();
+ for (; it != rows.end(); ++it)
+ {
+ ClVariable v = it->first;
+ const ClLinearExpression *pe = it->second;
+ xo << v << " <-=-> ";
+ if (pe) xo << *pe; else xo << "NilExpr";
+ xo << endl;
+ }
+ return xo;
+}
+
+ostream &operator<<(ostream &xo, const ClTableauRowsMap & rows)
+{ return PrintTo(xo,rows); }
+
+ostream &
+ClTableau::PrintOn(ostream &xo) const
+{
+ xo << "Tableau:\n"
+ << _rows << endl;
+ xo << "Columns:\n"
+ << _columns << endl;
+ xo << "Infeasible rows: "
+ << _infeasibleRows << endl;
+ xo << "External basic variables: "
+ << _externalRows << endl;
+ xo << "External parametric variables: "
+ << _externalParametricVars << endl;
+ return xo;
+}
+
+ostream &operator<<(ostream &xo, const ClTableau &clt)
+{ return clt.PrintOn(xo); }
+
+#endif
diff --git a/libs/cassowary/ClTests.cc b/libs/cassowary/ClTests.cc
new file mode 100644
index 0000000000..606d6f3e44
--- /dev/null
+++ b/libs/cassowary/ClTests.cc
@@ -0,0 +1,884 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClTests.cc
+
+#include <cassowary/Cl.h>
+#include <stdlib.h>
+#include <cassowary/timer.h>
+#include <iostream>
+#include <iomanip>
+
+inline
+double UniformRandom()
+{ return double(rand())/RAND_MAX; }
+
+
+bool
+simple1()
+{
+ try
+ {
+ bool fOkResult = true;
+ ClVariable x(167);
+ ClVariable y(2);
+ ClSimplexSolver solver;
+
+ ClLinearEquation eq(x,y+0.0);
+ solver.AddStay(x);
+ solver.AddStay(y);
+ solver.AddConstraint(eq);
+ cout << "x = " << x.Value() << endl
+ << "y = " << y.Value() << endl;
+ fOkResult = (x.Value() == y.Value());
+ return fOkResult;
+ }
+ catch (ExCLError &error)
+ {
+ cerr << "Exception! " << error.description() << endl;
+ return(false);
+ }
+ catch (...)
+ {
+ cerr << "Unknown exception" << endl;
+ return(false);
+ }
+}
+
+
+/* Add an edit variable to an empty solver */
+bool
+simple2()
+{
+ try
+ {
+ ClVariable x(167);
+ ClSimplexSolver solver;
+
+ solver.AddEditVar(x);
+ solver.BeginEdit();
+ solver.SuggestValue(x,100);
+ solver.EndEdit();
+
+ cout << "x = " << x.Value() << endl;
+ }
+ catch (ExCLEditMisuse &error)
+ {
+ cout << "Success: got the exception" << endl;
+ return true;
+ }
+ catch (ExCLError &error)
+ {
+ cerr << "Exception! " << error.description() << endl;
+ return(false);
+ }
+ catch (...)
+ {
+ cerr << "Unknown exception" << endl;
+ return(false);
+ }
+ cerr << "Should have gotten an exception!" << endl;
+ return false;
+}
+
+
+bool
+justStay1()
+{
+ try
+ {
+ bool fOkResult = true;
+ ClVariable x(5);
+ ClVariable y(10);
+ ClSimplexSolver solver;
+
+#if 0
+ solver.AddPointStay(x,y,1);
+#else
+ solver.AddStay(x);
+ solver.AddStay(y);
+#endif
+ fOkResult = fOkResult && ClApprox(x,5);
+ fOkResult = fOkResult && ClApprox(y,10);
+ cout << "x == " << x.Value() << endl;
+ cout << "y == " << y.Value() << endl;
+
+ return(fOkResult);
+ }
+ catch (ExCLError &error)
+ {
+ cerr << "Exception! " << error.description() << endl;
+ return(false);
+ }
+ catch (...)
+ {
+ cerr << "Unknown exception" << endl;
+ return(false);
+ }
+}
+
+
+
+bool
+addDelete1()
+{
+ try
+ {
+ bool fOkResult = true;
+ ClVariable x("x");
+ ClSimplexSolver solver;
+
+ solver.AddConstraint(new ClLinearEquation( x, 100, ClsWeak() ));
+
+ ClLinearInequality c10(x,cnLEQ,10.0);
+ ClLinearInequality c20(x,cnLEQ,20.0);
+ solver
+ .AddConstraint(c10)
+ .AddConstraint(c20);
+
+ fOkResult = fOkResult && ClApprox(x,10.0);
+ cout << "x == " << x.Value() << endl;
+
+ cout << endl << solver << endl;
+
+ solver.RemoveConstraint(c10);
+
+ cout << endl << solver << endl;
+
+ fOkResult = fOkResult && ClApprox(x,20.0);
+ cout << "x == " << x.Value() << endl;
+
+ solver.RemoveConstraint(c20);
+ fOkResult = fOkResult && ClApprox(x,100.0);
+ cout << "x == " << x.Value() << endl;
+
+ ClLinearInequality c10again(x,cnLEQ,10.0);
+
+ solver
+ .AddConstraint(c10)
+ .AddConstraint(c10again);
+
+ fOkResult = fOkResult && ClApprox(x,10.0);
+ cout << "x == " << x.Value() << endl;
+
+ solver.RemoveConstraint(c10);
+ fOkResult = fOkResult && ClApprox(x,10.0);
+ cout << "x == " << x.Value() << endl;
+
+ solver.RemoveConstraint(c10again);
+ fOkResult = fOkResult && ClApprox(x,100.0);
+ cout << "x == " << x.Value() << endl;
+
+ return(fOkResult);
+ }
+ catch (ExCLError &error)
+ {
+ cerr << "Exception! " << error.description() << endl;
+ return(false);
+ }
+ catch (...)
+ {
+ cerr << "Unknown exception" << endl;
+ return(false);
+ }
+}
+
+bool
+addDelete2()
+{
+ try
+ {
+ bool fOkResult = true;
+ ClVariable x("x");
+ ClVariable y("y");
+ ClSimplexSolver solver;
+
+ solver
+ .AddConstraint(new ClLinearEquation(x, 100.0, ClsWeak()))
+ .AddConstraint(new ClLinearEquation(y, 120.0, ClsStrong()));
+
+ ClLinearInequality c10(x,cnLEQ,10.0);
+ ClLinearInequality c20(x,cnLEQ,20.0);
+
+ solver
+ .AddConstraint(c10)
+ .AddConstraint(c20);
+ fOkResult = fOkResult && ClApprox(x,10.0) && ClApprox(y,120.0);
+ cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
+
+ solver.RemoveConstraint(c10);
+ fOkResult = fOkResult && ClApprox(x,20.0) && ClApprox(y,120.0);
+ cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
+
+ ClLinearEquation cxy( 2*x, y);
+ solver.AddConstraint(cxy);
+ fOkResult = fOkResult && ClApprox(x,20.0) && ClApprox(y,40.0);
+ cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
+
+ solver.RemoveConstraint(c20);
+ fOkResult = fOkResult && ClApprox(x,60.0) && ClApprox(y,120.0);
+ cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
+
+ solver.RemoveConstraint(cxy);
+ fOkResult = fOkResult && ClApprox(x,100.0) && ClApprox(y,120.0);
+ cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
+
+
+ return(fOkResult);
+ }
+ catch (ExCLError &error)
+ {
+ cerr << "Exception! " << error.description() << endl;
+ return(false);
+ }
+ catch (...)
+ {
+ cerr << "Unknown exception" << endl;
+ return(false);
+ }
+}
+
+bool
+casso1()
+{
+ try
+ {
+ bool fOkResult = true;
+ ClVariable x("x");
+ ClVariable y("y");
+ ClSimplexSolver solver;
+
+ solver
+ .AddConstraint(new ClLinearInequality(x,cnLEQ,y))
+ .AddConstraint(new ClLinearEquation(y, x+3.0))
+ .AddConstraint(new ClLinearEquation(x,10.0,ClsWeak()))
+ .AddConstraint(new ClLinearEquation(y,10.0,ClsWeak()))
+ ;
+
+ fOkResult = fOkResult &&
+ ( ClApprox(x,10.0) && ClApprox(y,13.0) ||
+ ClApprox(x,7.0) && ClApprox(y,10.0) );
+
+ cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
+
+ return(fOkResult);
+ }
+ catch (ExCLError &error)
+ {
+ cerr << "Exception! " << error.description() << endl;
+ return(false);
+ }
+ catch (...)
+ {
+ cerr << "Unknown exception" << endl;
+ return(false);
+ }
+}
+
+bool
+inconsistent1()
+{
+ ClSimplexSolver solver;
+ ClVariable x("x");
+ ClLinearEquation eq1(x,10.0);
+ ClLinearEquation eq2(x,5.0);
+ try
+ {
+
+ solver.AddConstraint( eq1 );
+ solver.AddConstraint( eq2 );
+
+ // no exception, we failed!
+ return(false);
+ }
+ catch (ExCLRequiredFailure)
+ {
+ // we want this exception to get thrown
+ cout << "Success -- got the exception" << endl;
+ // solver.RemoveConstraint(eq2); this would throw a constraint not found exception
+ // cout << solver << endl;
+ return(true);
+ }
+ catch (ExCLError &error)
+ {
+ cerr << "Exception! " << error.description() << endl;
+ return(false);
+ }
+ catch (...)
+ {
+ cerr << "Unknown exception" << endl;
+ return(false);
+ }
+}
+
+bool
+inconsistent2()
+{
+ try
+ {
+ ClVariable x("x");
+ ClSimplexSolver solver;
+
+ solver
+ .AddConstraint(new ClLinearInequality(x,cnGEQ,10.0))
+ .AddConstraint(new ClLinearInequality(x,cnLEQ, 5.0));
+
+ // no exception, we failed!
+ return(false);
+ }
+ catch (ExCLRequiredFailure &)
+ {
+ // we want this exception to get thrown
+ cout << "Success -- got the exception" << endl;
+ // cout << solver << endl;
+ return(true);
+ }
+ catch (ExCLError &error)
+ {
+ cerr << "Exception! " << error.description() << endl;
+ return(false);
+ }
+ catch (...)
+ {
+ cerr << "Unknown exception" << endl;
+ return(false);
+ }
+}
+
+bool
+inconsistent3()
+{
+ try
+ {
+ ClVariable w("w");
+ ClVariable x("x");
+ ClVariable y("y");
+ ClVariable z("z");
+ ClSimplexSolver solver;
+
+ solver
+ .AddConstraint(new ClLinearInequality(w,cnGEQ,10.0))
+ .AddConstraint(new ClLinearInequality(x,cnGEQ,w))
+ .AddConstraint(new ClLinearInequality(y,cnGEQ,x))
+ .AddConstraint(new ClLinearInequality(z,cnGEQ,y))
+ .AddConstraint(new ClLinearInequality(z,cnLEQ,4.0));
+
+ // no exception, we failed!
+ return(false);
+ }
+ catch (ExCLRequiredFailure &)
+ {
+ // we want this exception to get thrown
+ cout << "Success -- got the exception" << endl;
+ // cout << solver << endl;
+ return(true);
+ }
+ catch (ExCLError &error)
+ {
+ cerr << "Exception! " << error.description() << endl;
+ return(false);
+ }
+ catch (...)
+ {
+ cerr << "Unknown exception" << endl;
+ return(false);
+ }
+}
+
+
+bool
+multiedit()
+{
+ try
+ {
+ bool fOkResult = true;
+
+ ClVariable x("x",0);
+ ClVariable y("y",0);
+ ClVariable w("w",0);
+ ClVariable h("h",0);
+ ClSimplexSolver solver;
+
+ solver
+ .AddStay(x)
+ .AddStay(y)
+ .AddStay(w)
+ .AddStay(h);
+
+ solver
+ .AddEditVar(x)
+ .AddEditVar(y)
+ .BeginEdit();
+
+ solver
+ .SuggestValue(x,10)
+ .SuggestValue(y,20)
+ .Resolve();
+
+ cout << "x = " << x.Value() << "; y = " << y.Value() << endl
+ << "w = " << w.Value() << "; h = " << h.Value() << endl;
+
+ fOkResult = fOkResult &&
+ ClApprox(x,10) && ClApprox(y,20) && ClApprox(w,0) && ClApprox(h,0);
+
+ solver
+ .AddEditVar(w)
+ .AddEditVar(h)
+ .BeginEdit();
+
+ solver
+ .SuggestValue(w,30)
+ .SuggestValue(h,40)
+ .EndEdit();
+
+ cout << "x = " << x.Value() << "; y = " << y.Value() << endl
+ << "w = " << w.Value() << "; h = " << h.Value() << endl;
+
+ fOkResult = fOkResult &&
+ ClApprox(x,10) && ClApprox(y,20) && ClApprox(w,30) && ClApprox(h,40);
+
+ solver
+ .SuggestValue(x,50)
+ .SuggestValue(y,60)
+ .EndEdit();
+
+ cout << "x = " << x.Value() << "; y = " << y.Value() << endl
+ << "w = " << w.Value() << "; h = " << h.Value() << endl;
+
+ fOkResult = fOkResult &&
+ ClApprox(x,50) && ClApprox(y,60) && ClApprox(w,30) && ClApprox(h,40);
+
+ return fOkResult;
+ }
+ catch (ExCLError &error)
+ {
+ cerr << "Exception! " << error.description() << endl;
+ return(false);
+ }
+ catch (...)
+ {
+ cerr << "Unknown exception" << endl;
+ return(false);
+ }
+ cerr << "Should have gotten an exception!" << endl;
+ return false;
+}
+
+
+bool
+multiedit2()
+{
+ try
+ {
+ bool fOkResult = true;
+
+ ClVariable x("x",0);
+ ClVariable y("y",0);
+ ClVariable w("w",0);
+ ClVariable h("h",0);
+ ClSimplexSolver solver;
+
+ solver
+ .AddStay(x)
+ .AddStay(y)
+ .AddStay(w)
+ .AddStay(h);
+
+ solver
+ .AddEditVar(x)
+ .AddEditVar(y)
+ .BeginEdit();
+
+ solver
+ .SuggestValue(x,10)
+ .SuggestValue(y,20)
+ .Resolve();
+
+ cout << "x = " << x.Value() << "; y = " << y.Value() << endl
+ << "w = " << w.Value() << "; h = " << h.Value() << endl;
+
+ fOkResult = fOkResult &&
+ ClApprox(x,10) && ClApprox(y,20) && ClApprox(w,0) && ClApprox(h,0);
+
+ solver
+ .AddEditVar(x)
+ .AddEditVar(y)
+ .AddEditVar(w)
+ .AddEditVar(h)
+ .BeginEdit();
+
+ solver
+ .SuggestValue(w,30)
+ .SuggestValue(h,40)
+ .EndEdit();
+
+ cout << "x = " << x.Value() << "; y = " << y.Value() << endl
+ << "w = " << w.Value() << "; h = " << h.Value() << endl;
+
+ fOkResult = fOkResult &&
+ ClApprox(x,10) && ClApprox(y,20) && ClApprox(w,30) && ClApprox(h,40);
+
+ solver
+ .SuggestValue(x,50)
+ .SuggestValue(y,60)
+ .EndEdit();
+
+ cout << "x = " << x.Value() << "; y = " << y.Value() << endl
+ << "w = " << w.Value() << "; h = " << h.Value() << endl;
+
+ fOkResult = fOkResult &&
+ ClApprox(x,50) && ClApprox(y,60) && ClApprox(w,30) && ClApprox(h,40);
+
+ return fOkResult;
+ }
+ catch (ExCLError &error)
+ {
+ cerr << "Exception! " << error.description() << endl;
+ return(false);
+ }
+ catch (...)
+ {
+ cerr << "Unknown exception" << endl;
+ return(false);
+ }
+ cerr << "Should have gotten an exception!" << endl;
+ return false;
+}
+
+
+// From a bug report from Steve Wolfman on his
+// SAT project using "blackbox"
+bool
+blackboxsat()
+{
+ try
+ {
+ ClSimplexSolver solver;
+
+ ClVariable r1("r1");
+ ClVariable r2("r2");
+ ClVariable r3("r3");
+ ClVariable r4("r4");
+ ClVariable r5("r5");
+ ClVariable r6("r6");
+ ClVariable r7("r7");
+ ClVariable r8("r8");
+
+ ClConstraint *rgpcn[30];
+ for (int i=0; i<int(sizeof(rgpcn)/sizeof(rgpcn[0])); ++i)
+ rgpcn[i] = NULL;
+
+ rgpcn[1] = new ClLinearEquation(r1,60);
+ rgpcn[2] = new ClLinearEquation(r2,30);
+ rgpcn[12] = new ClLinearEquation(r3,2.5);
+ rgpcn[13] = new ClLinearEquation(r6,0);
+ rgpcn[14] = new ClLinearInequality(r5, cnGEQ, 0);
+ rgpcn[15] = new ClLinearInequality(r8, cnLEQ, 2.5);
+ rgpcn[16] = new ClLinearInequality(r7, cnGEQ, r6);
+ rgpcn[17] = new ClLinearInequality(r8, cnGEQ, r7);
+ rgpcn[18] = new ClLinearEquation(r4, r3 - r2/60.0);
+ rgpcn[19] = new ClLinearEquation(r5, r4 - r1/60.0);
+ rgpcn[20] = new ClLinearInequality(r4, cnGEQ, 0);
+ rgpcn[21] = new ClLinearInequality(r5, cnGEQ, 0);
+ rgpcn[22] = new ClLinearEquation(r7, r6 + r2/20.0);
+ rgpcn[23] = new ClLinearEquation(r8, r7 + r1/20.0);
+ rgpcn[24] = new ClLinearEquation(r4, r3 - r2/30.0);
+ rgpcn[25] = new ClLinearEquation(r5, r4 - r1/30.0);
+ rgpcn[26] = new ClLinearInequality(r4, cnGEQ, 0);
+ rgpcn[27] = new ClLinearInequality(r5, cnGEQ, 0);
+ rgpcn[28] = new ClLinearEquation(r7, r6 + r2/60.0);
+ rgpcn[29] = new ClLinearEquation(r8, r7 + r1/60.0);
+
+ while (true)
+ {
+ char szCmd[1000];
+ int i;
+ cin >> szCmd;
+ if (!cin)
+ break;
+ if (szCmd[0] == '#')
+ {
+ cin.getline(szCmd,900);
+ continue;
+ }
+ if (strcasecmp(szCmd,"Add") == 0)
+ {
+ cin >> i;
+ cout << "eq" << i << ": " << solver.AddConstraintNoException(rgpcn[i])
+ << "\t" << *(rgpcn[i]) << endl;
+ cout << r1 << " = " << r1.Value() << endl;
+ }
+ else if (strcasecmp(szCmd,"del") == 0)
+ {
+ cin >> i;
+ cout << "REMeq" << i << ": " << solver.RemoveConstraintNoException(rgpcn[i])
+ << "\t" << *(rgpcn[i]) << endl;
+ cout << r1 << " = " << r1.Value() << endl;
+ }
+ else if (strcasecmp(szCmd,"dump") == 0)
+ {
+ cout << solver << endl;
+ }
+ else if (strcasecmp(szCmd,"val") == 0)
+ {
+ cout << r1 << " = " << r1.Value() << endl;
+ }
+ else if (strcasecmp(szCmd,"solve") == 0)
+ {
+ cout << solver.Solve() << endl;
+ }
+ else if (strcasecmp(szCmd,"autosolve") == 0)
+ {
+ solver.SetAutosolve(true);
+ }
+ else if (strcasecmp(szCmd,"noautosolve") == 0)
+ {
+ solver.SetAutosolve(true);
+ }
+ }
+
+ cout << r1 << " = " << r1.Value() << endl
+ << r2 << " = " << r2.Value() << endl
+ << r3 << " = " << r3.Value() << endl
+ << r4 << " = " << r4.Value() << endl
+ << r5 << " = " << r5.Value() << endl
+ << r6 << " = " << r6.Value() << endl
+ << r7 << " = " << r7.Value() << endl
+ << r8 << " = " << r8.Value() << endl;
+
+ return false;
+ }
+ catch (ExCLError &error)
+ {
+ cerr << "Exception! " << error.description() << endl;
+ return(true);
+ }
+ catch (...)
+ {
+ cerr << "Unknown exception" << endl;
+ return(false);
+ }
+}
+
+typedef ClVariable *PClVariable;
+
+bool
+addDel(const int nCns = 900, const int nVars = 900, const int nResolves = 10000)
+//addDel(int nCns = 300, int nVars = 300, int nResolves = 1000)
+//addDel(int nCns = 30, int nVars = 30, int nResolves = 100)
+{
+ Timer timer;
+ // FIXGJB: from where did .12 come?
+ static const double ineqProb = 0.12;
+ static const int maxVars = 3;
+
+ cout << "starting timing test. nCns = " << nCns
+ << ", nVars = " << nVars << ", nResolves = " << nResolves << endl;
+
+ timer.Start();
+ ClSimplexSolver solver;
+ solver.SetAutosolve(false);
+
+ ClVariable **rgpclv = new PClVariable[nVars];
+ for (int i = 0; i < nVars; i++)
+ {
+ rgpclv[i] = new ClVariable(i,"x");
+ solver.AddStay(*rgpclv[i]);
+ }
+
+ ClConstraint **rgpcns = new PClConstraint[nCns];
+ int nvs = 0;
+ int k;
+ int j;
+ double coeff;
+ for (j = 0; j < nCns; j++)
+ {
+ // number of variables in this constraint
+ nvs = int(UniformRandom()*maxVars) + 1;
+ ClLinearExpression expr = UniformRandom()*20.0 - 10.0;
+ for (k = 0; k < nvs; k++)
+ {
+ coeff = UniformRandom()*10 - 5;
+ expr.AddExpression(*(rgpclv[int(UniformRandom()*nVars)]) * coeff);
+ }
+ if (UniformRandom() < ineqProb)
+ {
+ rgpcns[j] = new ClLinearInequality(expr);
+ }
+ else
+ {
+ rgpcns[j] = new ClLinearEquation(expr);
+ }
+#ifdef CL_SHOW_CNS_IN_BENCHMARK
+ cout << "Cn[" << j << "]: " << *rgpcns[j] << endl;
+#endif
+ }
+
+ cout << "done building data structures" << endl;
+ cout << "time = " << timer.ElapsedTime() << "\n" << endl;
+ timer.Start();
+ int cExceptions = 0;
+#ifdef CL_SHOW_CNS_IN_BENCHMARK
+ cout << "Exceptions on: ";
+#endif
+ for (j = 0; j < nCns; j++)
+ {
+ // Add the constraint -- if it's incompatible, just ignore it
+ try
+ {
+ solver.AddConstraint(rgpcns[j]);
+ }
+ catch (ExCLRequiredFailure &)
+ {
+ cExceptions++;
+ rgpcns[j] = NULL;
+#ifdef CL_SHOW_CNS_IN_BENCHMARK
+ cout << j << " ";
+#endif
+ }
+ }
+#ifdef CL_SHOW_CNS_IN_BENCHMARK
+ cout << "\n" << endl;
+#endif
+ solver.Solve();
+ cout << "done adding constraints [" << cExceptions << " exceptions]" << endl;
+ cout << "time = " << timer.ElapsedTime() << "\n" << endl;
+ cout << "time per cn = " << timer.ElapsedTime()/nCns << "\n" << endl;
+ cout << "time per actual cn = " << timer.ElapsedTime()/(nCns - cExceptions) << "\n" <<endl;
+ timer.Start();
+
+ int e1Index = int(UniformRandom()*nVars);
+ int e2Index = int(UniformRandom()*nVars);
+
+ ClVariable e1 = *(rgpclv[e1Index]);
+ ClVariable e2 = *(rgpclv[e2Index]);
+
+ solver
+ .AddEditVar(e1)
+ .AddEditVar(e2);
+
+ cout << "done creating edit constraints -- about to start resolves" << endl;
+ cout << "time = " << timer.ElapsedTime() << "\n" << endl;
+ timer.Start();
+
+ solver.BeginEdit();
+ // FIXGJB start = Timer.now();
+ for (int m = 0; m < nResolves; ++m)
+ {
+ solver
+ .SuggestValue(e1,e1->Value()*1.001)
+ .SuggestValue(e2,e2->Value()*1.001)
+ .Resolve();
+ }
+ solver.EndEdit();
+ // cout << "run time: " <<
+
+ cout << "done resolves -- now removing constraints" << endl;
+ cout << "time = " << timer.ElapsedTime() << "\n" <<endl;
+ cout << "time per Resolve = " << timer.ElapsedTime()/nResolves << "\n" <<endl;
+
+ timer.Start();
+
+ for (j = 0; j < nCns; j++)
+ {
+ if (rgpcns[j])
+ {
+ solver.RemoveConstraint(rgpcns[j]);
+ }
+ }
+
+ // FIXGJB end = Timer.now();
+ // cout << "Total remove time: "
+ // << "remove time per cn"
+ cout << "done removing constraints and addDel timing test" << endl;
+ cout << "time = " << timer.ElapsedTime() << "\n" <<endl;
+ cout << "time per cn = " << timer.ElapsedTime()/nCns << "\n" <<endl;
+ cout << "time per actual cn = " << timer.ElapsedTime()/(nCns - cExceptions) << "\n" <<endl;
+
+ for (int i = 0; i < nVars; i++)
+ {
+ delete rgpclv[i];
+ }
+
+ for (int j = 0; j < nCns; j++)
+ {
+ delete rgpcns[j];
+ }
+
+ return true;
+}
+
+
+int
+main( int argc, char **argv )
+{
+ try
+ {
+ bool fAllOkResult = true;
+ bool fResult;
+
+ // seed the random number generator for reproducible results
+ srand(123456789);
+
+ cout << "Cassowary version: " << szCassowaryVersion << endl;
+
+#define RUN_TEST(x) \
+ cout << #x << ":" << endl; \
+ fResult = x(); fAllOkResult &= fResult; \
+ if (!fResult) cout << "Failed!" << endl;
+
+ RUN_TEST(simple1);
+ RUN_TEST(simple2);
+ RUN_TEST(justStay1);
+ RUN_TEST(addDelete1);
+ RUN_TEST(addDelete2);
+ RUN_TEST(casso1);
+ RUN_TEST(inconsistent1);
+ RUN_TEST(inconsistent2);
+ RUN_TEST(inconsistent3);
+ RUN_TEST(multiedit);
+ RUN_TEST(multiedit2);
+ // RUN_TEST(blackboxsat);
+
+ int cns = 90, vars = 90, resolves = 100;
+
+ if (argc > 1)
+ cns = atoi(argv[1]);
+
+ if (argc > 2)
+ vars = atoi(argv[2]);
+
+ if (argc > 3)
+ resolves = atoi(argv[3]);
+
+ if (cns > 0)
+ {
+ cout << "addDel" << ":" << endl;
+ fResult = addDel(cns,vars,resolves); fAllOkResult &= fResult;
+ if (!fResult) cout << "Failed!" << endl;
+ }
+
+#undef RUN_TEST
+
+#ifdef CL_FIND_LEAK
+ cout << "ClAbstractVariables: " << ClAbstractVariable::cAbstractVariables
+ << "\nClDummyVariables: " << ClDummyVariable::cDummyVariables
+ << "\nClSlackVariables: " << ClSlackVariable::cSlackVariables
+ << endl;
+#endif
+
+
+ return (fAllOkResult? 0 : 255);
+
+ }
+ catch (...)
+ {
+ cerr << "exception!" << endl;
+ }
+}
diff --git a/libs/cassowary/ClVariable.cc b/libs/cassowary/ClVariable.cc
new file mode 100644
index 0000000000..2a136c1096
--- /dev/null
+++ b/libs/cassowary/ClVariable.cc
@@ -0,0 +1,21 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClVariable.cc
+
+#include <cassowary/ClVariable.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+StringToVarMap *ClVariable::pmapStrPclv = NULL;
+ClVariable clvNil(static_cast<ClAbstractVariable*>(0));
+
diff --git a/libs/cassowary/IMPORTANT b/libs/cassowary/IMPORTANT
new file mode 100644
index 0000000000..1edaabfa01
--- /dev/null
+++ b/libs/cassowary/IMPORTANT
@@ -0,0 +1,26 @@
+Cassowary/C++ needs to be compiled using a modern C++ compiler.
+At one time or another, it has compiled using:
+ o egcs-1.0.1, egcs-1.0.3, egcs-1.1b, gcc-2.8.1, gcc-2.95.2
+ o Visual C++ 5.0
+
+Cassowary/Java was developed using Sun's JDK-1.1.3, ported to Linux
+More recent versions should work fine, and it has been tested
+with JDK-1.2pre2.
+
+The included Makefiles depend upon features of GNU Make. See:
+
+ftp://ftp.gnu.org/pub/gnu/
+
+for a version that you can build.
+
+
+To build the c++/qdemos/QuadDemo application, you'll need TrollTech's Qt
+widget set for X11, available from:
+
+http://www.troll.no/dl/qtfree-dl.html
+
+
+See also the Scwm (Scheme Constraints Window Manager) web page for a use
+of Cassowary in a substantial application:
+
+http://scwm.mit.edu/scwm/
diff --git a/libs/cassowary/INSTALL b/libs/cassowary/INSTALL
new file mode 100644
index 0000000000..b42a17ac46
--- /dev/null
+++ b/libs/cassowary/INSTALL
@@ -0,0 +1,182 @@
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+ CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
diff --git a/libs/cassowary/LICENSE b/libs/cassowary/LICENSE
new file mode 100644
index 0000000000..21ecedf70d
--- /dev/null
+++ b/libs/cassowary/LICENSE
@@ -0,0 +1,18 @@
+Cassowary Constraint Solving Toolkit
+Copyright (C) 1998-200 Greg J. Badros
+
+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
+
+See COPYING.LGPL
diff --git a/libs/cassowary/Makefile.am b/libs/cassowary/Makefile.am
new file mode 100644
index 0000000000..fb36aef47c
--- /dev/null
+++ b/libs/cassowary/Makefile.am
@@ -0,0 +1,32 @@
+MAINTAINERCLEANFILES = autom4te.cache Makefile.in aclocal.m4 configure \
+ config.h.in stamp-h.in config.guess mkinstalldirs \
+ missing install-sh config.sub ltconfig \
+ ltmain.sh acinclude.m4 config.log config.status \
+ depcomp ClReader.cc ClReader.hh ClReader-lex.cc
+
+EXTRA_DIST = ClReader.l ClReader.y
+
+SUBDIRS = cassowary
+
+noinst_LIBRARIES = libcassowary.a
+
+libcassowary_a_SOURCES = \
+ ClAbstractVariable.cc \
+ ClConstraint.cc \
+ ClLinearExpression.cc \
+ ClSolver.cc \
+ ClSimplexSolver.cc \
+ ClStrength.cc \
+ ClSymbolicWeight.cc \
+ ClTableau.cc \
+ ClVariable.cc \
+ ClFloatVariable.cc \
+ ClSlackVariable.cc \
+ ClDummyVariable.cc \
+ ClReader-lex.cc
+
+ClReader-lex.cc: ClReader.l cassowary/ClReader.h ClReader.cc
+ $(LEX) -Pcl -o$@ $<
+
+ClReader.cc: ClReader.y cassowary/ClReader.h
+ $(YACC) -d -pcl --output-file $@ $<
diff --git a/libs/cassowary/NEWS b/libs/cassowary/NEWS
new file mode 100644
index 0000000000..0f950dacef
--- /dev/null
+++ b/libs/cassowary/NEWS
@@ -0,0 +1,229 @@
+Cassowary NEWS -- history of user-visible changes. -*- text -*-
+
+Cassowary Constraint Solving Toolkit was
+Implemented by:
+
+Greg J. Badros <gjb@cs.washington.edu> and
+Alan Borning <borning@cs.washington.edu>
+University of Washington
+Computer Science and Engineering
+Seattle, WA 98195-2350
+
+with Constraint Drawing Applet (CDA) by Michael Noth <noth@cs.washington.edu>
+
+12-March-2000: Version 0.60 released.
+* Changed license to LGPL!!!
+* Added SetAutoResetStayConstants(), FIsAutoResetStayConstants(), make ResetStayConstants() public
+
+29-Jan-2000: Version 0.55 released.
+* Some bug fixes
+* Added ClSimplexSolver::{ChangeStrength,ChangeStrengthAndWeight,ChangeWeight,
+ DisplayObjective,ExternalResetStayConstants} fns
+ From A. Beurivé.
+
+16-Dec-1999: Version 0.54a released.
+* Include correct version of OTI Smalltalk .dat file
+ (the source in the *.app files was right, the .dat file was old)
+* Fix java build bug
+
+15-Dec-1999: Version 0.54 released.
+* Bug fixes
+* auto-configuration improvements
+* Support Java 2 (jdk-1.2)
+* Improved ease of building Java demos
+* Build guile wrapper as long as guile-config works, use new --disable-guile-build to force off
+* Alpha-version of Java constraint parser contributed by Will Portnoy
+
+24-October-1999: Version 0.53 released.
+* Bug fixes
+* License exception for linking with Scwm.
+
+25-September-1999: Version 0.52 released.
+* Bug fix for nested edits where a later edit includes an already-being-edited variable
+
+14-September-1999: Version 0.51 released.
+* Minor bug fixes
+* Much better packaging, RPMs, etc. more forced reliance on GTL
+
+26-August-1999: Version 0.51 pre-releases begin
+
+12-July-1999: Version 0.50 released.
+* Made only C++ version build by default, --enable-java-build is needed to turn java on
+* Added restricted finite domain solver
+** needs --with-gtl configure option, and libGTL.{a,so*} to be installed
+* Added ClSolver base class, and use its type for pointers in callbacks
+
+14-Apr-1999: Version 0.43 released.
+* DEBUG_PARSE turned off by default
+* Added cassowary.spec for RPM building
+
+31-Mar-1999: Version 0.42 released.
+* Fixed autoconf bugs (.41 was a buggy release)
+* Added --disable-cpp-build,--disable-java-build, and disable Python/Guile builds
+automatically if directories cannot be found
+
+20-Mar-1999: Version 0.41 released.
+* Fixed bug in autoconf support -- config.sub, config.guess to the
+distribution so configure should actually work (they were symlinks
+before, in error).
+
+18-Mar-1999: Version 0.4 released.
+
+18-Mar-1999: Changes since Cassowary v0.32 (for release v0.4)
+* MUCH improved autoconf/automake support including numerous configure
+options, added libtool support.
+* Renamed many identifiers in the public API; this will break old code
+using Cassowary. See the scripts/convert-ids script for help converting
+your code (beware false positives; i.e., improper or unnecessary
+changes).
+
+
+10-Mar-1999: Changes since Cassowary v0.31 (for release v0.32)
+* Added automake/autoconf support. Old Makefiles are now
+Makefile.linux. This is not yet fully tested or correct, but I need to
+make a release now for the bug fixes. Consider compiling with "make -f
+Makefile.linux all" if you have problems running autoconf and/or
+automake.
+
+* Changes to C++
+** Bug fix for problem Anthony Beurivé noticed regarding removing non-1
+weight stay constraints.
+** Minor bug fix for parser. Also renamed the creader files to ClReader.
+
+* Changes to Java
+** Bug fix for problem Emmanuel Pietriga reported regarding edit
+constraints.
+** Improved debugging support a bit by adding descriptions to
+ExCLInternalError-s and assert()s
+
+* Changes to guile wrapper
+** changed name of library to libcassowaryguile.a from libconstraints.a
+
+
+1-Mar-1999: Changes since Cassowary v0.3 (for release v0.31)
+* Changes to C++
+** Some bug fixes -- pass ClVariable-s around by value instead of const
+& since they are now a handle class.
+** Changed output format for ClEditConstraint, ClStayConstraint instances
+** Use a function-object for controlling lookup/creation of variables in PcnParseConstraint
+** Fix bugs in creader.y parser (did not accept parens or division
+before). Introduced "==" as a a synonym for "="
+** Added szCassowaryVersion id string as a public char *.
+** Added ChangeStrength, ChangeWeight to ClConstraint's public
+interface, and have it valid only when the constraint is not in a solver
+** Added ClConstraint::FIsInSolver()
+
+* Changes to Guile wrapper
+** Fix bugs
+** Wrap parsing functionality, including a lambda for lookup/creation of
+variables
+** Build a dynamically-loadable guile module, update cltests.scm to use it
+
+
+23-Feb-1999: Version 0.3 released.
+
+19-Feb-1999, Changes since Cassowary v0.23 (for release v0.3)
+
+* Changes to Java and C++
+** Bug fix for Michael Kaufmann's report (see ChangeLog for details)
+** resolve(Vector..) procedure is now depracated; preferred interface is
+suggestValue(...) calls followed by resolve() (the one taking no
+arguments).
+** Added ClVariable::SetVarMap(..), ClVariable::VarMap() to permit
+ClVariable ctr to save the mapping between given name and actual object
+in a symbol table (used for parsing ascii expressions in C++ version)
+
+* Changes to just C++ implementation
+** Use ClVariable as a handle class to a ClAbstractVariable-- old
+ClVariable is now a ClFloatVariable. SetChangeClvCallback now takes a
+function that takes a ClVariable handle, not a pointer.
+** Passing ClConstraints's by const & is now deprecated -- pass by
+pointer to the ClConstraint object
+** Added creader.y, creader.l and function PcnParseConstraint(..) for
+creating a constraint from an ASCII string.
+** Added CL_NO_IO compile-time option to C++ version for preventing need
+to link with the stream library (is not complete)
+** Added CL_FIND_LEAK compile-time option for counting ctrs/dtr
+invocations
+** Added CL_USE_HASH_MAP compile-time option to permit using the GNU
+hash_map class instead of the standard STL map (which is a sorted
+associative container whose performance for lookups is logarithmic
+rather than constant time). Still does not work for me --02/16/99 gjb.
+
+* Changes to just Java implementation (updated to match changes to C++
+version for .2)
+** Added {get,set}AttachedObject for ClVariable, ClConstant
+** Permit access to ClSimplexSolver.ConstraintMap()
+** Permit nested beginEdit()s and handle them correctly
+
+* Miscellaneous changes
+** Updated copyright to include 1999
+** Fixed wrappers/Makefile for building Python wrapper
+** Reference Anthony Beurivé's STk wrapper
+** Fix Scwm URL
+
+
+30-Jan-1999, Changes since Cassowary v0.22 (for release v0.23)
+* Bug fix (see ChangeLog for details)
+
+
+23-Jan-1999, Changes since Cassowary v0.21 (for release v0.22)
+* Minor code cleanup, additions of comments.
+
+
+14-Sep-98, Changes since Cassowary v0.2 (for release v0.21)
+
+* Make compile cleanly using egcs-1.1b -- use typename, and drop
+ unused templated instantiation
+
+* Improved guile interface: add a void pointer to the solver objects,
+ and let the guile wrapper use it to keep a pointer to the scheme-level
+ object; also added clv-attach! and clv-attached-object for attaching
+ an object to a cl-variable (somewhat redundant with guile's
+ object properties)
+
+* Wrap ClStayConstraints so they can be managed explicitly
+
+* cl-add-stay, cl-add-editvar now take strength and factor arguments,
+ instead of a list of cl-vars
+
+* Added weight option to addEditVar
+
+
+6-Aug-98, Changes since Cassowary v0.1 (for release v0.2):
+
+* Changes to the distribution for release v0.2
+
+** added guile/scheme wrapper of C++ version
+
+** mention SCWM in README
+
+** mention non-maintenance of Smalltalk implementation unless we have users
+
+* Changes to the C++ and Java implementations
+
+** Fixed several bugs -- dummy variables were wrongly being pivoted into
+ the basis, and constraints that threw required failure exceptions
+ were mistakenly remaining in the tableau (now trying to remove an
+ exception that was not added because of a required-failure exception
+ will correctly throw a ConstraintNotFound exception); more -- see ChangeLog
+
+** Added a virtual change_value function to permit applications to watch
+ for changes made to external variables.
+
+* Changes to only the C++ version (Java version will catch up in 0.3)
+
+** Added new test cases to ClTests, fixed bugs in ClTestColumns
+
+** Added _pv (void *) field hanging off of ClConstraint and ClVariable
+ for associating arbitrary structs with those (needed by SCWM)
+
+** Permit nested beginEdit()s, and do the right thing upon calling
+ endEdit() -- i.e., not all the edit variables are removed, only the
+ nested ones
+
+** Permit access to ClSimplexSolver::ConstraintMap() (used by
+ guile-wrapper to efficiently get at a list of constraints in the
+ solver)
+
+** Added ExCLEditMisuse exception
diff --git a/libs/cassowary/README b/libs/cassowary/README
new file mode 100644
index 0000000000..16ed492b8e
--- /dev/null
+++ b/libs/cassowary/README
@@ -0,0 +1,241 @@
+Cassowary Constraint Solving Toolkit for C++, Java, and Smalltalk
+Version 0.60
+
+Web Page: http://www.cs.washington.edu/research/constraints/cassowary
+Contact: cassowary@cs.washington.edu
+
+Greg J. Badros <gjb@cs.washington.edu> and
+Alan Borning <borning@cs.washington.edu>
+University of Washington
+Computer Science and Engineering
+Seattle, WA 98195-2350
+12-March-2000
+
+with Constraint Drawing Applet (CDA) by Michael Noth <noth@cs.washington.edu>
+
+See ANNOUNCE for a brief description and announcement of this distribution.
+See NEWS for a history of user-visible changes.
+See ChangeLog for a detailed listing of the changes to each source file.
+See LICENSE for legalese regarding use of this distribution.
+
+The Smalltalk implementation is in the public domain -- see smalltalk/README.
+
+Please send bug reports to cassowary@cs.washington.edu
+
+Also, send mail to cassowary@cs.washington.edu if you would like to be
+informed about bug fixes, feature enhancements, etc. Let us know what
+implementation(s) you are using, too.
+
+------------------------------------------------------------------
+
+HOW TO GET STARTED
+
+The Cassowary library uses GNU autoconf to permit easy building on
+various platforms. You should be able to do:
+
+./configure
+make
+
+and everything will work. A more complex, but realistic example is:
+
+./configure --with-prefix=/usr/contrib \
+ --with-guile-prefix=/usr/contrib \
+ --with-python-headers=/usr/include/python1.5 \
+ --enable-java-build \
+ --with-gtl=/usr/contrib \
+ --with-java-class-path=/usr/contrib/share/java/site \
+ --enable-warnings
+make -k
+
+Be sure to give the extra --enable-permissive flag to configure if
+you are building with gcc-2.95 or more recent.
+
+As yet another data point, I build Cassowary with:
+
+./configure --with-guile-exec-prefix=/uns/bin \
+ --with-guile-prefix=/uns/share --prefix=/uns/share \
+ --exec-prefix=/uns --enable-maintainer-mode
+
+See the file "INSTALL" for more details about
+autoconf support and the options that the "configure" takes. You can
+also do "./configure --help" for the list of the options that configure
+accepts.
+
+If the make in any of the subdirectories fails, you can turn on the "-k"
+option to make, or just do make in the subdirectories that you want
+build. E.g., if you do not have the JDK installed, the Java version of
+Cassowary might not compile; if you still want the guile version, just
+"cd guile; make -k".
+
+Be sure that configure detects the validity of using the "-fpermissive"
+flag of more recent g++/egcs compilers to work around some
+const-discrepancies between the const-challenged guile header files and
+Cassowary's more const-correct usage. You should get a message like:
+
+ checking whether gcc understands -fpermissive option... yes
+
+when running configure if you're using, e.g., gcc-2.95 or later.
+
+You need to apply GTL.h.patch to the installed GTL.h header file for
+Cassowary to compile with recent versions of egcs/gcc (e.g., gcc-2.95).
+
+Also, you may need to change libguile/gsubr.h from:
+
+ extern SCM scm_make_gsubr SCM_P ((char *name, int req, int opt,
+ int rst, SCM (*fcn)()));
+ to
+
+ extern SCM scm_make_gsubr SCM_P ((char *name, int req, int opt,
+ int rst, void*));
+
+or patch guile's snarf.h to insert the appropriate case at each call to
+SCM_PROC and SCM_PROC1. (Thanks to Alexandre Duret-Lutz for the above
+information about more recent g++/egcs compilers).
+
+Note that the generated Makefiles depend upon features of GNU Make. See:
+
+ftp://ftp.gnu.org/pub/gnu/
+
+for a version of make that you can build first to then build Cassowary.
+
+Example applications exist in subdirectories of the top-level
+implementation subdirectories (e.g., c++/qdemos contains demos for C++
+that use the Qt Widget toolkit).
+
+Please send mail to cassowary@cs.washington.edu if you are using this
+toolkit so we know how to reach you for bug fixes, updates, etc.
+
+------------------------------------------------------------------
+
+WHAT THE DISTRIBUTION CONTAINS
+
+This distribution contains 3 implementations of the Cassowary constraint
+solving toolkit:
+
+o C++
+o Java
+o Smalltalk
+
+For each implementation language, there is at least one example program;
+for some there are many.
+
+There is a wrapping of the C++ solver in Guile-Scheme -- see the guile/
+subdirectory. Also, Anthony Beurivé has wrapped Cassowary for
+STk/Scheme. His code is available at:
+
+ http://dept-info.labri.u-bordeaux.fr/~beurive/Code
+
+and the STk Scheme system is available at:
+
+ http://kaolin.unice.fr/STk/
+
+There is also a SWIG-generated wrapper of the C++ library making the
+solver available from the Python language.
+
+A technical report describing the solver, its interface, and its
+implementation is in cassowary-tr.ps (pdf version in cassowary-tr.pdf).
+This paper is required reading if you intend to use the solver in your
+own project(s).
+
+See also the Scwm (Scheme Constraints Window Manager) web page:
+
+http://scwm.mit.edu/scwm/
+
+Scwm, also by Greg Badros (and Maciej Stachowiak), is the most
+substantial application using this toolkit that we are aware of.
+
+------------------------------------------------------------------
+
+VARIOUS IMPLEMENTATION NOTES
+
+Cassowary/C++ needs to be compiled using a modern C++ compiler.
+At one time or another, it has compiled using:
+ o egcs-1.0.1
+ o egcs-1.0.3a
+ o egcs-1.1b
+ o egcs-1.1.1
+ o gcc-2.8.1 (needs libstdc++-2.8.x, too)
+ o Visual C++ 5.0 (not tried recently)
+
+In particular, Cassowary will *not* build with gcc-2.7.x.x!
+
+See c++/README for more details about building the C++ version.
+
+The C++ implementation of the toolkit also has an optional finite domain
+subsolver. You need to build and install the GTL -- the Graph Template
+Library -- and use the "--with-gtl=DIR" configure option for the finite
+domain subsolver to be built. GTL is available from:
+
+http://www.fmi.uni-passau.de/Graphlet/GTL/
+
+Cassowary was tested against GTL-0.3.1; it may work with later
+versions, but I have not tried it. You need to apply GTL.h.patch to
+the installed GTL.h header file for Cassowary to compile with recent
+versions of egcs/gcc (e.g., gcc-2.95).
+
+Cassowary/Java was developed using Sun's JDK-1.1.x, ported to Linux
+More recent versions should work fine.
+
+See java/README for more details about building the Java version.
+
+
+Cassowary/Smalltalk was written under OTI Smalltalk-- other versions of
+smalltalk will likely require (possibly significant) changes.
+
+See smalltalk/README for more details about the Smalltalk version.
+
+See guile/README for details about the Guile Scheme wrapper of the C++
+implementation, and for a pointer to SCWM, the Scheme Constraints Window
+Manager which uses Cassowary.
+
+The Python bindings (by Tessa Lau) bindings for the Cassowary library
+are in the wrappers/ subdirectory. SWIG was used in wrapping the
+library. These bindings may no longer work, and are provided only for
+your hacking pleasure (please send back useful patches if you do get the
+code working).
+
+For more information about SWIG, see:
+
+http://www.swig.org/
+
+
+For more information about the Python language, see:
+
+http://www.python.org/
+
+
+For more information about the Guile-Scheme language, see:
+
+http://www.red-bean.com/guile/
+http://www.fsf.org/software/guile/guile.html
+
+
+------------------------------------------------------------------
+
+DEMONSTRATION APPLICATION
+
+A standard demonstration application is included for each implementation
+of the Cassowary solver. The application builds a quadrilateral and
+connects the neighboring midpoints of each of the outer edges to form an
+interior quadrilateral which is provably a parallelogram. The
+constraint solver manages the constraints to keep the outer
+quadrilateral inside the window, keep the midpoints properly positioned,
+and keep the outer quadrilateral from turning "inside out."
+
+The user is able to select points (draggable boxes) and move them around
+within the window (both midpoints and endpoints can be selected, of
+course). The solver updates the figure, and redraws.
+
+
+------------------------------------------------------------------
+
+FUNDING ACKNOWLEDGEMENTS
+
+This work has been funded in part by the National Science Foundation under
+Grants IRI-9302249 and CCR-9402551, by Object Technology International, and
+by a Fulbright Award from the Australian-American Educational
+Foundation.
+
+Additionally, Greg Badros is supported by a National Science Foundation
+Graduate Research Fellowship. Parts of this material are based upon
+work supported under that fellowship.
diff --git a/libs/cassowary/THANKS b/libs/cassowary/THANKS
new file mode 100644
index 0000000000..11918b3d52
--- /dev/null
+++ b/libs/cassowary/THANKS
@@ -0,0 +1,30 @@
+Cassowary Constraint Solving Toolkit was
+Implemented by:
+
+Greg J. Badros <gjb@cs.washington.edu> and
+Alan Borning <borning@cs.washington.edu>
+University of Washington
+Computer Science and Engineering
+Seattle, WA 98195-2350
+
+with Constraint Drawing Applet (CDA) by Michael Noth <noth@cs.washington.edu>
+
+Please send bug reports to cassowary@cs.washington.edu
+
+
+Bug reports, helpful testing, and/or code from:
+
+Spencer Allain
+Anthony Beurivé
+Robert Chassell
+Alexandre 'Pollux' Duret-Lutz
+Michael Kaufmann
+Brian Grant
+Pengling He
+Tessa Lau
+John MacPhail
+Larry Melia
+Michael Noth
+Emmanuel Pietriga
+Will Portnoy
+Steve Wolfman
diff --git a/libs/cassowary/autogen.sh b/libs/cassowary/autogen.sh
new file mode 100644
index 0000000000..4d1bcb29e5
--- /dev/null
+++ b/libs/cassowary/autogen.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+aclocal $ACLOCAL_FLAGS && autoheader && automake --add-missing && autoconf
+
diff --git a/libs/cassowary/cassowary-config b/libs/cassowary/cassowary-config
new file mode 100755
index 0000000000..172237763e
--- /dev/null
+++ b/libs/cassowary/cassowary-config
@@ -0,0 +1,102 @@
+#!/bin/sh
+# Modified from gtk-config
+# --09/07/99 gjb
+
+# gotten from LDADD in c++/Makefile.am
+cassowary_gtllibs=""
+cassowary_libs="-L/usr/local/lib $cassowary_gtllibs"
+cassowary_cflags="-I/usr/local/include "
+
+prefix=/usr/local
+exec_prefix=${prefix}
+exec_prefix_set=no
+
+usage()
+{
+ cat <<EOF
+Usage: cassowary-config [OPTIONS]
+Options:
+ [--prefix[=DIR]]
+ [--exec-prefix[=DIR]]
+ [--version]
+ [--libs]
+ [--gtllibs]
+ [--cflags]
+EOF
+ exit $1
+}
+
+if test $# -eq 0; then
+ usage 1 1>&2
+fi
+
+while test $# -gt 0; do
+ case "$1" in
+ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ case $1 in
+ --prefix=*)
+ prefix=$optarg
+ if test $exec_prefix_set = no ; then
+ exec_prefix=$optarg
+ fi
+ ;;
+ --prefix)
+ echo_prefix=yes
+ ;;
+ --exec-prefix=*)
+ exec_prefix=$optarg
+ exec_prefix_set=yes
+ ;;
+ --exec-prefix)
+ echo_exec_prefix=yes
+ ;;
+ --version)
+ echo 0.60
+ ;;
+ --cflags)
+ echo_cflags=yes
+ ;;
+ --libs)
+ echo_libs=yes
+ ;;
+ --gtllibs)
+ echo_gtllibs=yes
+ ;;
+ *)
+ usage 1 1>&2
+ ;;
+ esac
+ shift
+done
+
+if test "$echo_prefix" = "yes"; then
+ echo $prefix
+fi
+
+if test "$echo_exec_prefix" = "yes"; then
+ echo $exec_prefix
+fi
+
+
+if test "$echo_cflags" = "yes"; then
+ if test ${prefix}/include != /usr/include ; then
+ includes=-I${prefix}/include
+ for i in $cassowary_cflags ; do
+ if test $i = -I${prefix}/include ; then
+ includes=""
+ fi
+ done
+ fi
+ echo $includes $cassowary_cflags
+fi
+
+if test "$echo_libs" = "yes"; then
+ echo -L${exec_prefix}/lib -lcassowary -lstdc++ $cassowary_libs
+fi
+
+if test "$echo_gtllibs" = "yes"; then
+ echo $cassowary_gtllibs
+fi
diff --git a/libs/cassowary/cassowary-config.in b/libs/cassowary/cassowary-config.in
new file mode 100755
index 0000000000..ac1b3ac8ce
--- /dev/null
+++ b/libs/cassowary/cassowary-config.in
@@ -0,0 +1,102 @@
+#!/bin/sh
+# Modified from gtk-config
+# --09/07/99 gjb
+
+# gotten from LDADD in c++/Makefile.am
+cassowary_gtllibs="@GTL_LIB@"
+cassowary_libs="-L@prefix@/lib $cassowary_gtllibs"
+cassowary_cflags="@GUILE_INCLUDES@ @GTL_INCLUDES@"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+exec_prefix_set=no
+
+usage()
+{
+ cat <<EOF
+Usage: cassowary-config [OPTIONS]
+Options:
+ [--prefix[=DIR]]
+ [--exec-prefix[=DIR]]
+ [--version]
+ [--libs]
+ [--gtllibs]
+ [--cflags]
+EOF
+ exit $1
+}
+
+if test $# -eq 0; then
+ usage 1 1>&2
+fi
+
+while test $# -gt 0; do
+ case "$1" in
+ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ case $1 in
+ --prefix=*)
+ prefix=$optarg
+ if test $exec_prefix_set = no ; then
+ exec_prefix=$optarg
+ fi
+ ;;
+ --prefix)
+ echo_prefix=yes
+ ;;
+ --exec-prefix=*)
+ exec_prefix=$optarg
+ exec_prefix_set=yes
+ ;;
+ --exec-prefix)
+ echo_exec_prefix=yes
+ ;;
+ --version)
+ echo @CASSOWARY_VERSION@
+ ;;
+ --cflags)
+ echo_cflags=yes
+ ;;
+ --libs)
+ echo_libs=yes
+ ;;
+ --gtllibs)
+ echo_gtllibs=yes
+ ;;
+ *)
+ usage 1 1>&2
+ ;;
+ esac
+ shift
+done
+
+if test "$echo_prefix" = "yes"; then
+ echo $prefix
+fi
+
+if test "$echo_exec_prefix" = "yes"; then
+ echo $exec_prefix
+fi
+
+
+if test "$echo_cflags" = "yes"; then
+ if test @includedir@ != /usr/include ; then
+ includes=-I@includedir@
+ for i in $cassowary_cflags ; do
+ if test $i = -I@includedir@ ; then
+ includes=""
+ fi
+ done
+ fi
+ echo $includes $cassowary_cflags
+fi
+
+if test "$echo_libs" = "yes"; then
+ echo -L@libdir@ -lcassowary -lstdc++ $cassowary_libs
+fi
+
+if test "$echo_gtllibs" = "yes"; then
+ echo $cassowary_gtllibs
+fi
diff --git a/libs/cassowary/cassowary-nofd.spec2 b/libs/cassowary/cassowary-nofd.spec2
new file mode 100644
index 0000000000..d1abb93c5f
--- /dev/null
+++ b/libs/cassowary/cassowary-nofd.spec2
@@ -0,0 +1,84 @@
+# Note that this is NOT a relocatable package
+%define ver 0.60
+%define rel 2
+%define prefix /usr
+
+Name: cassowary-nofd
+Summary: A Linear Arithmetic Constraint Solving Library.
+Version: %ver
+Release: %rel
+# This source just has a different top-level directory name
+Source: http://www.cs.washington.edu/research/constraints/cassowary/cassowary-nofd-%ver.tar.gz
+Group: Development/Libraries
+BuildRoot: /tmp/cassowary-%ver-build
+Copyright: Copyright (C) 1998,1999 Greg J. Badros
+Packager: Greg J. Badros <gjb@cs.washington.edu>
+URL: http://www.cs.washington.edu/research/constraints/cassowary
+Requires: guile >= 1.3.2
+Provides: cassowary-constraint-solver
+
+%description
+
+Cassowary is an advanced incremental constraint solving toolkit that
+efficiently solves systems of linear equalities and inequalities.
+Constraints may be either requirements or preferences. Client code
+specifies the constraints to be maintained, and the solver updates the
+constrained variables to have values that satisfy the constraints.
+
+This package lacks the finite domain subsolver. The cassowary RPM
+contains that solver as well, but also requires the GTL (Graph
+Template Library) package.
+
+
+%changelog
+* Tue Sep 7 1999 Greg J. Badros <gjb@cs.washington.edu)
+- Added cassowary-nofd package to remove GTL dependence, added provides
+ virtual package "cassowary-constraint-solver" so that both this .spec
+ and cassowary.spec can provide it
+
+* Sat Sep 4 1999 Greg J. Badros <gjb@cs.washington.edu)
+- Use -fpermissive if it is available, fix --enable-warnings
+
+* Wed Aug 25 1999 Greg J. Badros <gjb@cs.washington.edu>
+- Rework spec file.
+
+* Wed Apr 14 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+- Initial release of this package.
+
+%prep
+
+%setup
+
+%build
+ln -sf . ./c++/cassowary
+
+%ifarch alpha
+./configure --host=alpha-linux --prefix=%prefix --enable-guile-build --enable-fsstd --enable-permissive
+%else
+./configure --prefix=%prefix --enable-guile-build --enable-fsstd --enable-permissive
+%endif
+
+make
+
+%install
+make prefix=$RPM_BUILD_ROOT%{prefix} install-strip
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+
+%postun
+
+%files
+%defattr(-, root, root)
+
+%{prefix}/bin/*
+%{prefix}/lib/*
+%{prefix}/include/*
+
+%doc ANNOUNCE AUTHORS COPYING IMPORTANT INSTALL LICENSE NEWS README THANKS
+%doc ChangeLog docs/cassowary-tr.pdf docs/cassowary-tr.ps.gz
+%doc guile/cassowary_scm-procedures.txt guile/cassowary_scm-variables.txt
+%doc guile/cassowary_scm.sgml
diff --git a/libs/cassowary/cassowary-nofd.spec2.in b/libs/cassowary/cassowary-nofd.spec2.in
new file mode 100644
index 0000000000..ee951bb446
--- /dev/null
+++ b/libs/cassowary/cassowary-nofd.spec2.in
@@ -0,0 +1,84 @@
+# Note that this is NOT a relocatable package
+%define ver @VERSION@
+%define rel 2
+%define prefix /usr
+
+Name: cassowary-nofd
+Summary: A Linear Arithmetic Constraint Solving Library.
+Version: %ver
+Release: %rel
+# This source just has a different top-level directory name
+Source: http://www.cs.washington.edu/research/constraints/cassowary/cassowary-nofd-%ver.tar.gz
+Group: Development/Libraries
+BuildRoot: /tmp/cassowary-%ver-build
+Copyright: Copyright (C) 1998,1999 Greg J. Badros
+Packager: Greg J. Badros <gjb@cs.washington.edu>
+URL: http://www.cs.washington.edu/research/constraints/cassowary
+Requires: guile >= 1.3.2
+Provides: cassowary-constraint-solver
+
+%description
+
+Cassowary is an advanced incremental constraint solving toolkit that
+efficiently solves systems of linear equalities and inequalities.
+Constraints may be either requirements or preferences. Client code
+specifies the constraints to be maintained, and the solver updates the
+constrained variables to have values that satisfy the constraints.
+
+This package lacks the finite domain subsolver. The cassowary RPM
+contains that solver as well, but also requires the GTL (Graph
+Template Library) package.
+
+
+%changelog
+* Tue Sep 7 1999 Greg J. Badros <gjb@cs.washington.edu)
+- Added cassowary-nofd package to remove GTL dependence, added provides
+ virtual package "cassowary-constraint-solver" so that both this .spec
+ and cassowary.spec can provide it
+
+* Sat Sep 4 1999 Greg J. Badros <gjb@cs.washington.edu)
+- Use -fpermissive if it is available, fix --enable-warnings
+
+* Wed Aug 25 1999 Greg J. Badros <gjb@cs.washington.edu>
+- Rework spec file.
+
+* Wed Apr 14 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+- Initial release of this package.
+
+%prep
+
+%setup
+
+%build
+ln -sf . ./c++/cassowary
+
+%ifarch alpha
+./configure --host=alpha-linux --prefix=%prefix --enable-guile-build --enable-fsstd --enable-permissive
+%else
+./configure --prefix=%prefix --enable-guile-build --enable-fsstd --enable-permissive
+%endif
+
+make
+
+%install
+make prefix=$RPM_BUILD_ROOT%{prefix} install-strip
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+
+%postun
+
+%files
+%defattr(-, root, root)
+
+%{prefix}/bin/*
+%{prefix}/lib/*
+%{prefix}/include/*
+
+%doc ANNOUNCE AUTHORS COPYING IMPORTANT INSTALL LICENSE NEWS README THANKS
+%doc ChangeLog docs/cassowary-tr.pdf docs/cassowary-tr.ps.gz
+%doc guile/cassowary_scm-procedures.txt guile/cassowary_scm-variables.txt
+%doc guile/cassowary_scm.sgml
diff --git a/libs/cassowary/cassowary.spec b/libs/cassowary/cassowary.spec
new file mode 100644
index 0000000000..bd30177048
--- /dev/null
+++ b/libs/cassowary/cassowary.spec
@@ -0,0 +1,78 @@
+# Note that this is NOT a relocatable package
+%define ver 0.60
+%define rel 1
+%define prefix /usr
+
+Name: cassowary
+Summary: A Linear Arithmetic Constraint Solving Library.
+Version: %ver
+Release: %rel
+Source: http://www.cs.washington.edu/research/constraints/cassowary/cassowary-%ver.tar.gz
+Group: Development/Libraries
+BuildRoot: /tmp/cassowary-%ver-build
+Copyright: Copyright (C) 1998,1999 Greg J. Badros
+Packager: Greg J. Badros <gjb@cs.washington.edu>
+URL: http://www.cs.washington.edu/research/constraints/cassowary
+Requires: guile >= 1.3.4
+Requires: GTL >= 0.3.1
+Provides: cassowary-constraint-solver
+
+%description
+
+Cassowary is an advanced incremental constraint solving toolkit that
+efficiently solves systems of linear equalities and inequalities.
+Constraints may be either requirements or preferences. Client code
+specifies the constraints to be maintained, and the solver updates the
+constrained variables to have values that satisfy the constraints.
+
+%changelog
+* Tue Sep 7 1999 Greg J. Badros <gjb@cs.washington.edu)
+- added provides virtual package "cassowary-constraint-solver" so that
+ both this .spec and cassowary.spec can provide it
+
+* Sat Sep 4 1999 Greg J. Badros <gjb@cs.washington.edu)
+- Use -fpermissive if it is available, fix --enable-warnings
+
+* Wed Aug 25 1999 Greg J. Badros <gjb@cs.washington.edu>
+- Rework spec file.
+
+* Wed Apr 14 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+- Initial release of this package.
+
+%prep
+
+%setup
+
+%build
+ln -sf . ./c++/cassowary
+
+%ifarch alpha
+fake_root_for_install=$RPM_BUILD_ROOT ./configure --host=alpha-linux --prefix=%prefix --with-gtl=%prefix --enable-fd-solver --enable-fsstd --enable-permissive
+%else
+fake_root_for_install=$RPM_BUILD_ROOT ./configure --prefix=%prefix --with-gtl=%prefix --enable-fd-solver --enable-fsstd --enable-permissive
+%endif
+
+make
+
+%install
+make prefix=$RPM_BUILD_ROOT%{prefix} fake_root_for_install=$RPM_BUILD_ROOT install-strip
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+
+%postun
+
+%files
+%defattr(-, root, root)
+
+%{prefix}/bin/*
+%{prefix}/lib/*
+%{prefix}/include/*
+
+%doc ANNOUNCE AUTHORS COPYING IMPORTANT INSTALL LICENSE NEWS README THANKS
+%doc ChangeLog docs/cassowary-tr.pdf docs/cassowary-tr.ps.gz
+%doc guile/cassowary_scm-procedures.txt guile/cassowary_scm-variables.txt
+%doc guile/cassowary_scm.sgml
diff --git a/libs/cassowary/cassowary.spec.in b/libs/cassowary/cassowary.spec.in
new file mode 100644
index 0000000000..2b7c23a8e5
--- /dev/null
+++ b/libs/cassowary/cassowary.spec.in
@@ -0,0 +1,78 @@
+# Note that this is NOT a relocatable package
+%define ver @VERSION@
+%define rel 1
+%define prefix /usr
+
+Name: cassowary
+Summary: A Linear Arithmetic Constraint Solving Library.
+Version: %ver
+Release: %rel
+Source: http://www.cs.washington.edu/research/constraints/cassowary/cassowary-%ver.tar.gz
+Group: Development/Libraries
+BuildRoot: /tmp/cassowary-%ver-build
+Copyright: Copyright (C) 1998,1999 Greg J. Badros
+Packager: Greg J. Badros <gjb@cs.washington.edu>
+URL: http://www.cs.washington.edu/research/constraints/cassowary
+Requires: guile >= 1.3.4
+Requires: GTL >= 0.3.1
+Provides: cassowary-constraint-solver
+
+%description
+
+Cassowary is an advanced incremental constraint solving toolkit that
+efficiently solves systems of linear equalities and inequalities.
+Constraints may be either requirements or preferences. Client code
+specifies the constraints to be maintained, and the solver updates the
+constrained variables to have values that satisfy the constraints.
+
+%changelog
+* Tue Sep 7 1999 Greg J. Badros <gjb@cs.washington.edu)
+- added provides virtual package "cassowary-constraint-solver" so that
+ both this .spec and cassowary.spec can provide it
+
+* Sat Sep 4 1999 Greg J. Badros <gjb@cs.washington.edu)
+- Use -fpermissive if it is available, fix --enable-warnings
+
+* Wed Aug 25 1999 Greg J. Badros <gjb@cs.washington.edu>
+- Rework spec file.
+
+* Wed Apr 14 1999 Greg J. Badros <gjb@cs.washington.edu>
+
+- Initial release of this package.
+
+%prep
+
+%setup
+
+%build
+ln -sf . ./c++/cassowary
+
+%ifarch alpha
+fake_root_for_install=$RPM_BUILD_ROOT ./configure --host=alpha-linux --prefix=%prefix --with-gtl=%prefix --enable-fd-solver --enable-fsstd --enable-permissive
+%else
+fake_root_for_install=$RPM_BUILD_ROOT ./configure --prefix=%prefix --with-gtl=%prefix --enable-fd-solver --enable-fsstd --enable-permissive
+%endif
+
+make
+
+%install
+make prefix=$RPM_BUILD_ROOT%{prefix} fake_root_for_install=$RPM_BUILD_ROOT install-strip
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+
+%postun
+
+%files
+%defattr(-, root, root)
+
+%{prefix}/bin/*
+%{prefix}/lib/*
+%{prefix}/include/*
+
+%doc ANNOUNCE AUTHORS COPYING IMPORTANT INSTALL LICENSE NEWS README THANKS
+%doc ChangeLog docs/cassowary-tr.pdf docs/cassowary-tr.ps.gz
+%doc guile/cassowary_scm-procedures.txt guile/cassowary_scm-variables.txt
+%doc guile/cassowary_scm.sgml
diff --git a/libs/cassowary/cassowary/.cvsignore b/libs/cassowary/cassowary/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/libs/cassowary/cassowary/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/libs/cassowary/cassowary/Cassowary.h b/libs/cassowary/cassowary/Cassowary.h
new file mode 100644
index 0000000000..8413f321f9
--- /dev/null
+++ b/libs/cassowary/cassowary/Cassowary.h
@@ -0,0 +1,40 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// Cassowary.h
+
+#ifndef Cassowary_H
+#define Cassowary_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+ #include <cassowary/config-inline.h>
+ #define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#ifndef CL_PTR_HASH_DIVISOR
+ #define CL_PTR_HASH_DIVISOR 4
+#endif
+
+#include "ClConstraintHash.h"
+#include <climits>
+
+#include <string>
+#include <cassert>
+#include <iostream>
+
+typedef double Number;
+
+typedef long FDNumber;
+
+enum { FDN_NOTSET = LONG_MIN };
+
+#define NEWVAR(x) do { cerr << "line " << __LINE__ << ": new " << x << endl; } while (0)
+#define DELVAR(x) do { cerr << "line " << __LINE__ << ": del " << x << endl; } while (0)
+
+#endif // Cassowary_H
diff --git a/libs/cassowary/cassowary/Cl.h b/libs/cassowary/cassowary/Cl.h
new file mode 100644
index 0000000000..6c2604da6f
--- /dev/null
+++ b/libs/cassowary/cassowary/Cl.h
@@ -0,0 +1,49 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// Cl.h
+// This is the top level include file for external clients
+
+#ifndef CL_H
+#define CL_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#ifdef CL_NO_IO
+#undef CL_TRACE
+#undef CL_SOLVER_STATS
+#undef CL_DEBUG_FAILURES
+#undef CL_TRACE_VERBOSE
+#endif
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "cassowary/ClVariable.h"
+#include "cassowary/ClSimplexSolver.h"
+#include "cassowary/ClLinearEquation.h"
+#include "cassowary/ClLinearInequality.h"
+#include "cassowary/ClErrors.h"
+#include "cassowary/ClEditConstraint.h"
+#include "cassowary/ClStayConstraint.h"
+#include "cassowary/ClReader.h"
+#include "cassowary/ClConstraint.h"
+#if defined(CL_HAVE_GTL) && defined(CL_BUILD_FD_SOLVER)
+#include "cassowary/ClFDBinaryOneWayConstraint.h"
+#include "cassowary/ClFDSolver.h"
+#endif
+
+extern const char *szCassowaryVersion;
+
+#endif
diff --git a/libs/cassowary/cassowary/ClAbstractVariable.h b/libs/cassowary/cassowary/ClAbstractVariable.h
new file mode 100644
index 0000000000..08ade9ec98
--- /dev/null
+++ b/libs/cassowary/cassowary/ClAbstractVariable.h
@@ -0,0 +1,161 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClAbstractVariable.h
+
+#ifndef ClAbstractVariable_H
+#define ClAbstractVariable_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include <cstdio> /* for sprintf */
+#include "Cassowary.h"
+#include "ClErrors.h"
+#include <memory>
+#include <string>
+#include <iostream>
+#include "cl_auto_ptr.h"
+
+using std::string;
+using std::ostream;
+
+class ClAbstractVariable {
+public:
+ ClAbstractVariable(string Name = "") :
+ _name(Name), _pv(0)
+ {
+ ++iVariableNumber;
+#ifdef CL_FIND_LEAK
+ ++cAbstractVariables;
+#endif
+ if (Name.length() == 0)
+ {
+ char sz[16];
+ sprintf(sz,"v%ld",iVariableNumber);
+ _name = string(sz);
+ }
+ }
+
+ ClAbstractVariable(long varnumber, char *prefix) :
+ _pv(0)
+ {
+ cl_auto_ptr<char> pch (new char[16+strlen(prefix)]);
+ iVariableNumber++;
+#ifdef CL_FIND_LEAK
+ ++cAbstractVariables;
+#endif
+ sprintf(pch.get(),"%s%ld",prefix,varnumber);
+ _name = string(pch.get());
+ }
+
+ virtual ~ClAbstractVariable()
+#ifdef CL_FIND_LEAK
+ { --cAbstractVariables; }
+
+ static long cAbstractVariables;
+#else
+ { }
+#endif
+
+ // Return the Name of the variable
+ string Name() const
+ { return _name; }
+
+ // Set the Name of the variable
+ virtual void SetName(string const &Name)
+ { _name = Name; }
+
+ // Return true iff this variable is a ClFloatVariable
+ virtual bool IsFloatVariable() const
+ { return false; }
+
+ // Return true iff this variable is a ClFDVariable
+ virtual bool IsFDVariable() const
+ { return false; }
+
+ // Return true if this a dummy variable (used as a marker variable
+ // for required equality constraints). Such variables aren't
+ // allowed to enter the basis when pivoting.
+ virtual bool IsDummy() const
+ { return false; }
+
+ // Return true if this a variable known outside the solver.
+ // (We need to give such variables a Value after solving is complete.)
+ virtual bool IsExternal() const
+ { return false; }
+
+ // Return true if we can Pivot on this variable.
+ virtual bool IsPivotable() const
+ { throw ExCLTooDifficultSpecial("Variable not usable inside SimplexSolver"); return false; }
+
+ // Return true if this is a restricted (or slack) variable. Such
+ // variables are constrained to be non-negative and occur only
+ // internally to the simplex solver.
+ virtual bool IsRestricted() const
+ { throw ExCLTooDifficultSpecial("Variable not usable inside SimplexSolver"); return false; }
+
+#ifndef CL_NO_IO
+ // Prints a semi-descriptive representation to the stream, using the
+ // Name if there is one, and otherwise the hash number of this
+ // object.
+ // EXAMPLES
+ // x[10.0] -- w/ Name
+ // x[0.0,100] -- w/ Name, bounds but no Value yet
+ // CV#345(10.0) -- w/o Name
+ virtual ostream &PrintOn(ostream &xo) const = 0;
+
+ friend ostream& operator<<(ostream &xos, const ClAbstractVariable &clv)
+ { clv.PrintOn(xos); return xos; }
+
+#endif // CL_NO_IO
+
+ friend bool operator<(const ClAbstractVariable &cl1, const ClAbstractVariable &cl2)
+ { return &cl1 < &cl2; }
+
+ friend bool operator==(const ClAbstractVariable &cl1, const ClAbstractVariable &cl2)
+ {
+ return &cl1 == &cl2;
+ }
+
+ friend bool operator!=(const ClAbstractVariable &cl1, const ClAbstractVariable &cl2)
+ {
+ return !(cl1 == cl2);
+ }
+
+ virtual Number Value() const { return 0; }
+ virtual int IntValue() const { return 0; }
+
+ virtual void SetValue(Number)
+ { assert(false); }
+
+ virtual void ChangeValue(Number)
+ { assert(false); }
+
+ void SetPv(void *pv)
+ { _pv = pv; }
+
+ void *Pv() const
+ { return _pv; }
+
+private:
+ string _name;
+
+ static long iVariableNumber;
+
+ // C-style extension mechanism so I
+ // don't have to wrap ScwmClVariables separately
+ void *_pv;
+};
+
+typedef ClAbstractVariable *PClAbstractVariable;
+
+#endif
diff --git a/libs/cassowary/cassowary/ClConstraint.h b/libs/cassowary/cassowary/ClConstraint.h
new file mode 100644
index 0000000000..0b670e6c07
--- /dev/null
+++ b/libs/cassowary/cassowary/ClConstraint.h
@@ -0,0 +1,198 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClConstraint.h
+
+#ifndef ClConstraint_H
+#define ClConstraint_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "debug.h"
+
+#include "Cassowary.h"
+#include "ClLinearExpression.h"
+#include "ClStrength.h"
+#include <string>
+
+using std::string;
+
+class ClSimplexSolver;
+class ClFDSolver;
+class ClBlueSolver;
+
+// enum setup so additive inverse flips the direction of the inequality
+enum ClCnRelation {cnEQ = 0, cnNEQ = 100, cnLEQ = 2, cnGEQ = -2, cnLT = 3, cnGT = -3 };
+
+inline enum ClCnRelation
+ReverseInequality(enum ClCnRelation c)
+{
+ if (c != cnNEQ)
+ c = (enum ClCnRelation) (- int(c));
+ return c;
+}
+
+inline string
+StrCnRelation(enum ClCnRelation rel) {
+ switch (rel) {
+ case cnEQ: return "=";
+ case cnNEQ: return "=/=";
+ case cnLEQ: return "<=";
+ case cnGEQ: return ">=";
+ case cnLT: return "<";
+ case cnGT: return ">";
+ default: assert(false);
+ }
+}
+
+
+
+class ClConstraint {
+public:
+
+ ClConstraint(const ClStrength &strength = ClsRequired(), double weight = 1.0 ) :
+ _strength(strength),
+ _readOnlyVars(),
+ _weight(weight),
+ _pv(0),
+ _times_added(0)
+ {
+ CtrTracer(__FUNCTION__,this);
+ }
+
+ virtual ~ClConstraint()
+ {
+ DtrTracer(__FUNCTION__,this);
+ }
+
+ // Return my linear Expression. (For linear equations, this
+ // constraint represents Expression=0; for linear inequalities it
+ // represents Expression>=0.)
+ virtual ClLinearExpression Expression() const
+ { assert(false); }
+
+ // Returns true if this is an edit constraint
+ virtual bool IsEditConstraint() const
+ { return false; }
+
+ // Return true if this is an inequality constraint and
+ // false if it is an equality constraint. The default is
+ // that it is not.
+ virtual bool IsInequality() const
+ { return false; }
+
+ virtual bool IsStrictInequality() const
+ { return false; }
+
+ virtual bool IsRequired() const
+ { return _strength.IsRequired(); }
+
+ virtual bool isStayConstraint() const
+ { return false; }
+
+ virtual const ClStrength &strength() const
+ { return _strength; }
+
+ virtual double weight() const
+ { return _weight; }
+
+#ifndef CL_NO_IO
+ virtual ostream &PrintOn(ostream &xo) const = 0;
+
+ friend ostream& operator<<(ostream &xos, const ClConstraint &constraint)
+ { constraint.PrintOn(xos); return xos; }
+
+#endif
+
+
+ void SetPv(void *pv)
+ { _pv = pv; }
+
+ void *Pv() const
+ { return _pv; }
+
+ virtual bool FIsSatisfied() const { return false; }
+
+ virtual bool FIsInSolver() const { return _times_added != 0; }
+
+ virtual bool FIsOkayForSimplexSolver() const { return true; }
+
+ void ChangeStrength( const ClStrength &strength)
+ {
+ if (_times_added == 0) {
+ setStrength(strength);
+ } else {
+ throw ExCLTooDifficult();
+ }
+ }
+
+ void ChangeWeight( double weight )
+ {
+ if (_times_added == 0) {
+ setWeight(weight);
+ } else {
+ throw ExCLTooDifficult();
+ }
+ }
+
+ bool FIsReadOnlyVar(ClVariable v) const {
+ return !(_readOnlyVars.find(v) == _readOnlyVars.end());
+ }
+
+ const ClVarSet &ReadOnlyVars() const {
+ return _readOnlyVars;
+ }
+
+ ClConstraint &AddROVars(const ClVarSet &setClv) {
+ for ( ClVarSet::const_iterator it = setClv.begin();
+ it != setClv.end(); ++it) {
+ _readOnlyVars.insert(*it);
+ }
+ return *this;
+ }
+
+ friend class ClSimplexSolver;
+ friend class ClFDSolver;
+ friend class ClBlueSolver;
+private:
+
+ ClSymbolicWeight symbolicWeight() const {
+ return _strength.symbolicWeight();
+ }
+
+ void addedTo(const ClSimplexSolver &)
+ { ++_times_added; }
+
+ void removedFrom(const ClSimplexSolver &)
+ { --_times_added; }
+
+ void setStrength( const ClStrength &strength )
+ { _strength = strength; }
+
+ void setWeight( double weight )
+ { _weight = weight; }
+
+ /// instance variables
+ ClStrength _strength;
+
+ ClVarSet _readOnlyVars;
+
+ double _weight;
+
+ void *_pv;
+
+ int _times_added;
+};
+
+typedef ClConstraint* PClConstraint;
+
+#endif
diff --git a/libs/cassowary/cassowary/ClConstraintHash.h b/libs/cassowary/cassowary/ClConstraintHash.h
new file mode 100644
index 0000000000..9d51fad311
--- /dev/null
+++ b/libs/cassowary/cassowary/ClConstraintHash.h
@@ -0,0 +1,39 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClHash.h
+
+#ifndef CL_HASH_H__
+#define CL_HASH_H__
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#ifdef CL_USE_HASH_MAP_AND_SET
+
+#include <hash_map>
+
+class ClConstraint;
+
+struct hash<const ClConstraint *> {
+ size_t operator()(const ClConstraint * const p) const
+ { return size_t((unsigned long)p/CL_PTR_HASH_DIVISOR); }
+};
+
+struct hash<ClConstraint *> {
+ size_t operator()(ClConstraint * const p) const
+ { return size_t((unsigned long)p/CL_PTR_HASH_DIVISOR); }
+};
+
+#endif // CL_USE_HASH_MAP_AND_SET
+
+
+#endif
diff --git a/libs/cassowary/cassowary/ClDummyVariable.h b/libs/cassowary/cassowary/ClDummyVariable.h
new file mode 100644
index 0000000000..ad959a6d20
--- /dev/null
+++ b/libs/cassowary/cassowary/ClDummyVariable.h
@@ -0,0 +1,88 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClDummyVariable.h
+
+#ifndef ClDummyVariable_H
+#define ClDummyVariable_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+#include "ClAbstractVariable.h"
+
+class ClTableau;
+class ClSimplexSolver;
+
+class ClDummyVariable : public ClAbstractVariable {
+
+public:
+
+#ifdef CL_FIND_LEAK
+ ~ClDummyVariable() { --cDummyVariables; };
+
+ static long cDummyVariables;
+
+#endif
+
+protected:
+ friend class ClTableau;
+ friend class ClSimplexSolver;
+
+ ClDummyVariable(string Name = "") :
+ ClAbstractVariable(Name)
+ {
+#ifdef CL_FIND_LEAK
+ ++cDummyVariables;
+#endif
+ }
+
+ ClDummyVariable(long number, char *prefix) :
+ ClAbstractVariable(number,prefix)
+ {
+#ifdef CL_FIND_LEAK
+ ++cDummyVariables;
+#endif
+ }
+
+#ifndef CL_NO_IO
+ virtual ostream &PrintOn(ostream &xo) const
+ {
+ xo << "[" << Name() << ":dummy]";
+ return xo;
+ }
+#endif
+
+ // Return true if this a dummy variable (used as a marker variable
+ // for required equality constraints). Such variables aren't
+ // allowed to enter the basis when pivoting.
+ virtual bool IsDummy() const
+ { return true; }
+
+ // Return true if this a variable known outside the solver.
+ // (We need to give such variables a Value after solving is complete.)
+ virtual bool IsExternal() const
+ { return false; }
+
+ // Return true if we can Pivot on this variable.
+ virtual bool IsPivotable() const
+ { return false; }
+
+ // Return true if this is a restricted (or slack) variable. Such
+ // variables are constrained to be non-negative and occur only
+ // internally to the simplex solver.
+ virtual bool IsRestricted() const
+ { return true; }
+
+};
+
+#endif
diff --git a/libs/cassowary/cassowary/ClEditConstraint.h b/libs/cassowary/cassowary/ClEditConstraint.h
new file mode 100644
index 0000000000..4bd91e2ca2
--- /dev/null
+++ b/libs/cassowary/cassowary/ClEditConstraint.h
@@ -0,0 +1,45 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClEditConstraint.h
+
+#ifndef ClEditConstraint_H
+#define ClEditConstraint_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+#include "ClEditOrStayConstraint.h"
+
+class ClEditConstraint : public ClEditOrStayConstraint {
+ typedef ClEditOrStayConstraint super;
+ public:
+
+ ClEditConstraint(const ClVariable var,
+ const ClStrength &strength = ClsStrong(), double weight = 1.0 ) :
+ ClEditOrStayConstraint(var,strength,weight)
+ { }
+
+ // Returns true if this is an edit constraint
+ virtual bool IsEditConstraint() const
+ { return true; }
+
+#ifndef CL_NO_IO
+ virtual ostream &PrintOn(ostream &xo) const
+ { super::PrintOn(xo); return xo << "= edit)"; }
+#endif
+
+ private:
+
+};
+
+#endif
diff --git a/libs/cassowary/cassowary/ClEditOrStayConstraint.h b/libs/cassowary/cassowary/ClEditOrStayConstraint.h
new file mode 100644
index 0000000000..79b6761b69
--- /dev/null
+++ b/libs/cassowary/cassowary/ClEditOrStayConstraint.h
@@ -0,0 +1,51 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClEditOrStayConstraint.h
+
+#ifndef ClEditOrStayConstraint_H
+#define ClEditOrStayConstraint_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "ClConstraint.h"
+#include "ClLinearExpression.h"
+
+class ClVariable;
+
+class ClEditOrStayConstraint : public ClConstraint {
+ public:
+
+ ClEditOrStayConstraint(const ClVariable var,
+ const ClStrength &strength = ClsRequired(), double weight = 1.0 ) :
+ ClConstraint(strength,weight),
+ _variable(var)
+ { }
+
+ const ClVariable variable() const
+ { return _variable; }
+
+ ClLinearExpression Expression() const
+ { return ClLinearExpression(_variable,-1,_variable.Value()); }
+
+ private:
+
+ void setVariable( const ClVariable v)
+ { _variable = v; }
+
+ /// instance variables
+ ClVariable _variable;
+
+
+};
+
+#endif
diff --git a/libs/cassowary/cassowary/ClErrors.h b/libs/cassowary/cassowary/ClErrors.h
new file mode 100644
index 0000000000..867c578dbc
--- /dev/null
+++ b/libs/cassowary/cassowary/ClErrors.h
@@ -0,0 +1,179 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClErrors.h
+
+#ifndef ClErrors_H
+#define ClErrors_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+#include "ClTypedefs.h"
+#include <string>
+#include <exception>
+
+using std::string;
+using std::exception;
+
+class ExCLError : public exception {
+ public:
+ ExCLError() : _msg(0) { }
+ virtual ~ExCLError() throw() {}
+ virtual string description() const
+ { return "(ExCLError) An error has occured in CL"; }
+ protected:
+ char *_msg;
+};
+
+class ExCLInternalError : public ExCLError {
+ public:
+ ExCLInternalError(const char *sz)
+ { _msg = strdup(sz); }
+ virtual string description() const
+ {
+ if (_msg) return _msg;
+ else return "(ExCLInternalError) An internal error has occurred";
+ }
+};
+
+class ExCLBadResolve : public ExCLError {
+ public:
+ ExCLBadResolve(const char *sz)
+ { _msg = strdup(sz); }
+ virtual string description() const
+ {
+ if (_msg) return _msg;
+ else return "(ExCLBadResolve) Number of resolve values did not match number of edit vars";
+ }
+};
+
+class ExCLEditMisuse : public ExCLError {
+ public:
+ ExCLEditMisuse(const char *sz)
+ { _msg = strdup(sz); }
+ virtual string description() const
+ {
+ if (_msg) return _msg;
+ return "(ExCLEditMisuse) Edit protocol usage violation";
+ }
+};
+
+class ExCLTooDifficult : public ExCLError {
+ public:
+ virtual string description() const
+ { return "(ExCLTooDifficult) The constraints are too difficult to solve"; }
+};
+
+class ExCLTooDifficultSpecial : public ExCLTooDifficult {
+ public:
+ ExCLTooDifficultSpecial(const char *sz)
+ { _msg = strdup(sz); }
+ virtual string description() const
+ {
+ if (_msg) return _msg;
+ else return "(ExCLTooDifficultSpecial) Solver requirements are not satisfied";
+ }
+};
+
+class ExCLReadOnlyNotAllowed : public ExCLTooDifficult {
+ public:
+ virtual string description() const
+ { return "(ExCLReadOnlyNotAllowed) The read-only annotation is not permitted by the solver"; }
+};
+
+class ExCLCycleNotAllowed : public ExCLTooDifficult {
+ public:
+ virtual string description() const
+ { return "(ExCLCycleNotAllowed) A cyclic constraint graph is not permitted by the solver"; }
+};
+
+class ExCLStrictInequalityNotAllowed : public ExCLTooDifficult {
+ public:
+ virtual string description() const
+ { return "(ExCLStrictInequalityNotAllowed) The strict inequality is not permitted by the solver"; }
+};
+
+class ExCLRequiredFailure : public ExCLError {
+ public:
+ virtual ~ExCLRequiredFailure() throw() {}
+ virtual string description() const
+ { return "(ExCLRequiredFailure) A required constraint cannot be satisfied"; }
+};
+
+class ExCLNotEnoughStays : public ExCLError {
+ public:
+ virtual string description() const
+ { return "(ExCLNotEnoughStays) There are not enough stays to give specific values to every variable"; }
+};
+
+class ExCLNonlinearExpression : public ExCLError {
+ public:
+ virtual string description() const
+ { return "(ExCLNonlinearExpression) The resulting expression would be nonlinear"; }
+};
+
+class ExCLConstraintNotFound : public ExCLError {
+ public:
+ virtual string description() const
+ { return "(ExCLConstraintNotFound) Tried to remove a constraint that was never added"; }
+};
+
+class ExCLParseError : public ExCLError {
+ public:
+ virtual ~ExCLParseError() throw() {}
+ virtual string description() const
+ { return "(ExCLParseError)"; }
+};
+
+class ExCLParseErrorMisc : public ExCLParseError {
+ public:
+ ExCLParseErrorMisc(const string &s)
+ : _msg("(ExCLParseError) ")
+ { _msg += s; }
+ virtual ~ExCLParseErrorMisc() throw() {}
+ virtual string description() const
+ { return _msg; }
+ private:
+ string _msg;
+};
+
+class ExCLParseErrorBadIdentifier : public ExCLParseError {
+ public:
+ ExCLParseErrorBadIdentifier(const string &id)
+ : _msg("(ExCLParseErrorBadIdentifier) Did not recognize identifier '")
+ {
+ _msg += id;
+ _msg += "'";
+ }
+ virtual ~ExCLParseErrorBadIdentifier() throw() {}
+ virtual string description() const
+ { return _msg; }
+ private:
+ string _msg;
+};
+
+class ExCLRequiredFailureWithExplanation : public ExCLRequiredFailure
+{
+public:
+ virtual ~ExCLRequiredFailureWithExplanation() throw() {}
+ virtual string description() const
+ { return "(ExCLRequiredFailureWithExplanation) A required constraint cannot be satisfied"; }
+ virtual void AddConstraint(const ClConstraint *cnExpl)
+ { _explanation.insert(cnExpl); }
+ virtual const ClConstraintSet & explanation() const
+ { return _explanation; }
+protected:
+ ClConstraintSet _explanation;
+};
+
+#endif // ClErrors_H
diff --git a/libs/cassowary/cassowary/ClFDBinaryOneWayConstraint.h b/libs/cassowary/cassowary/ClFDBinaryOneWayConstraint.h
new file mode 100644
index 0000000000..a779ec1f91
--- /dev/null
+++ b/libs/cassowary/cassowary/ClFDBinaryOneWayConstraint.h
@@ -0,0 +1,94 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClFDBinaryOneWayConstraint.h
+
+#ifndef ClFDBinaryOneWayConstraint_H
+#define ClFDBinaryOneWayConstraint_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+#include "ClFDConstraint.h"
+
+class ClLinearConstraint;
+
+// Just a node in the class hierarchy for now
+class ClFDBinaryOneWayConstraint : public ClFDConstraint {
+ private: typedef ClFDConstraint super;
+
+ public:
+
+ ClFDBinaryOneWayConstraint(ClVariable vRW, enum ClCnRelation rel, ClVariable vRO,
+ double coefficient = 1.0, double constant = 0.0,
+ const ClStrength &strength = ClsRequired(),
+ double weight = 1.0)
+ : ClFDConstraint(strength,weight), _vRW(vRW), _rel(rel), _vRO(vRO),
+ _coefficient(coefficient), _constant(constant)
+ { }
+
+ ClFDBinaryOneWayConstraint(ClVariable vRW, enum ClCnRelation rel, double constant,
+ const ClStrength &strength = ClsRequired(),
+ double weight = 1.0)
+ : ClFDConstraint(strength,weight), _vRW(vRW), _rel(rel), _vRO(clvNil),
+ _coefficient(0), _constant(constant)
+ { }
+
+ ClFDBinaryOneWayConstraint(const ClConstraint &cn);
+
+ static void EnsurePreconditionsForCn(const ClConstraint &cn);
+
+ static bool FCanConvertCn(const ClConstraint &cn);
+
+#ifndef CL_NO_IO
+ virtual ostream &PrintOn(ostream &xo) const
+ {
+ xo << "FDCn: " << _vRW << " " << StrCnRelation(_rel) << " ";
+ if (_coefficient != 0) {
+ if (_coefficient != 1) xo << _coefficient << "*";
+ if (_vRO != clvNil) xo << _vRO;
+ }
+ if (_constant != 0) xo << " + " << _constant;
+ return xo;
+ }
+
+ friend ostream& operator<<(ostream &xos, const ClFDBinaryOneWayConstraint &constraint)
+ { return constraint.PrintOn(xos); }
+
+#endif
+
+ ClVariable ClvRW() const
+ { return _vRW; }
+ ClVariable ClvRO() const
+ { return _vRO; }
+ enum ClCnRelation Relation() const
+ { return _rel; }
+ double Coefficient() const
+ { return _coefficient; }
+ double Constant() const
+ { return _constant; }
+
+ bool IsInequality() const
+ { return (_rel != cnEQ && _rel != cnNEQ); }
+
+ bool IsStrictInequality() const
+ { return (_rel == cnGT || _rel == cnLT); }
+
+ protected:
+ ClVariable _vRW;
+ enum ClCnRelation _rel;
+ ClVariable _vRO;
+ double _coefficient;
+ double _constant;
+};
+
+#endif
diff --git a/libs/cassowary/cassowary/ClFDConnectorVariable.h b/libs/cassowary/cassowary/ClFDConnectorVariable.h
new file mode 100644
index 0000000000..4ae38ae42e
--- /dev/null
+++ b/libs/cassowary/cassowary/ClFDConnectorVariable.h
@@ -0,0 +1,89 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClFDConnectorVariable.h
+
+#ifndef ClFDConnectorVariable_H
+#define ClFDConnectorVariable_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include <stdio.h>
+#include <map>
+#include <string>
+#include <list>
+#include "Cassowary.h"
+#include "ClVariable.h"
+#include "ClFDVariable.h"
+#include "ClLinearEquation.h"
+#include "ClSimplexSolver.h"
+
+/* Creates a new variable in the FD region
+ that sets clvFloat in solver (simplex region)
+ when it changes */
+class ClFDConnectorVariable : public ClFDVariable {
+public:
+ typedef ClFDVariable super;
+
+ ClFDConnectorVariable(string name, FDNumber Value, const list<FDNumber> &initial_domain,
+ ClSimplexSolver &solver, ClVariable clvFloat) :
+ ClFDVariable(name,Value,initial_domain),
+ _solver(solver),
+ _clvFloat(clvFloat),
+ _pcnRequiredLink(new ClLinearEquation(clvFloat,Value))
+ { solver.AddConstraint(_pcnRequiredLink); }
+
+#ifndef CL_NO_IO
+ // Prints a semi-descriptive representation to the stream, using the
+ // name if there is one, and otherwise the hash number of this
+ // object.
+ // EXAMPLE
+ // [x:10.0] -- name = "x", Value = 10.0
+ virtual ostream &PrintOn(ostream &xo) const;
+#endif
+
+ // permit overriding in subclasses in case something needs to be
+ // done when the Value is changed by the solver
+ // may be called when the Value hasn't actually changed -- just
+ // means the solver is setting the external variable
+ virtual void ChangeValue(FDNumber Value)
+ {
+ if (_value != Value) {
+ _value = Value;
+ cerr << "Updating " << _clvFloat << " now!" << endl;
+ _solver.RemoveConstraint(_pcnRequiredLink);
+ _pcnRequiredLink->ChangeConstant(_value);
+ _solver.AddConstraint(_pcnRequiredLink);
+ }
+ }
+
+private:
+
+ // similar to SetValue -- see caveat above -- made private for now
+ // since it's probably the wrong thing and is too easy to invoke
+ FDNumber operator=(FDNumber Value)
+ { _value = Value; return Value; }
+
+ // Copy constructor left undefined since we want to
+ // outlaw passing by Value! Will get a link error if you
+ // try to use within ClFDConnectorVariable.c, compile-time error everywhere else
+ ClFDConnectorVariable(const ClFDConnectorVariable &);
+
+ ClSimplexSolver &_solver;
+
+ ClVariable _clvFloat;
+
+ ClLinearEquation *_pcnRequiredLink;
+
+};
+
+#endif
diff --git a/libs/cassowary/cassowary/ClFDConstraint.h b/libs/cassowary/cassowary/ClFDConstraint.h
new file mode 100644
index 0000000000..2cf9776449
--- /dev/null
+++ b/libs/cassowary/cassowary/ClFDConstraint.h
@@ -0,0 +1,40 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClFDConstraint.h
+
+#ifndef ClFDConstraint_H
+#define ClFDConstraint_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+#include "ClConstraint.h"
+
+
+// Just a node in the class hierarchy for now
+class ClFDConstraint : public ClConstraint {
+ private: typedef ClConstraint super;
+
+ public:
+ // Constructor
+ ClFDConstraint(const ClStrength &strength = ClsRequired(),
+ double weight = 1.0)
+ : ClConstraint(strength, weight) { }
+
+ virtual bool FIsOkayForSimplexSolver() const { return false; }
+
+ protected:
+
+};
+
+#endif
diff --git a/libs/cassowary/cassowary/ClFDSolver.h b/libs/cassowary/cassowary/ClFDSolver.h
new file mode 100644
index 0000000000..2fbb637764
--- /dev/null
+++ b/libs/cassowary/cassowary/ClFDSolver.h
@@ -0,0 +1,120 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClSolver.h
+
+#ifndef ClFDSolver_H
+#define ClFDSolver_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+#include "ClSolver.h"
+#include "ClVariable.h"
+#include "ClErrors.h"
+#include "ClTypedefs.h"
+#include "ClSymbolicWeight.h"
+#include <GTL/graph.h>
+#include <map>
+
+using std::map;
+
+class ClVariable;
+class ClFDBinaryOneWayConstraint;
+
+// ClFDSolver is a concrete class
+// implementing a very restricted (for now --04/23/99 gjb)
+// finite-domain constraint solving algorithm
+class ClFDSolver: public ClSolver {
+ public:
+ ClFDSolver()
+ : _setCns(), _mapClvToCns(), G(), nodeToVar(G)
+ { G.make_directed(); }
+
+ virtual ~ClFDSolver()
+ { }
+
+ virtual ClFDSolver &AddConstraint(ClConstraint *const pcn);
+
+ virtual ClFDSolver &RemoveConstraint(ClConstraint *const pcn);
+
+ virtual ClFDSolver &Solve();
+
+ virtual ClFDSolver &ShowSolve();
+
+ void ChangeClv(ClVariable clv, FDNumber n) {
+ clv.ChangeValue(n);
+ if (_pfnChangeClvCallback) {
+ _pfnChangeClvCallback(&clv,this);
+ }
+ }
+
+
+#ifndef CL_NO_IO
+ ostream &PrintOn(ostream &xo) const;
+
+ ostream &PrintInternalInfo(ostream &xo) const;
+
+ ostream &PrintOnVerbose(ostream &xo) const
+ { PrintOn(xo); PrintInternalInfo(xo); xo << endl; return xo; }
+
+ friend ostream &operator<<(ostream &xo, const ClFDSolver &solver);
+
+#endif
+
+ protected:
+
+ virtual ClFDSolver &AddConstraintInternal(ClConstraint *const pcn);
+
+ virtual ClFDSolver &RemoveConstraintInternal(ClConstraint *const pcn);
+
+ /* Create node for v in G, if necessary,
+ otherwise return the node we already created. */
+ node GetVarNode(ClVariable v);
+
+ /* return the best (lowest) incremental error and the value
+ at which that error occurs */
+ pair<ClSymbolicWeight,FDNumber> ComputeBest(ClFDVariable *pcldv);
+
+ ClSymbolicWeight ErrorForClvAtValSubjectToCn(ClFDVariable *pcldv,
+ FDNumber value,const ClConstraint &cn);
+
+ /* Turn all FDVariable FIsSet() flags to false */
+ void ResetSetFlagsOnVariables();
+
+ /* all the constraints in the solver */
+ ClConstraintSet _setCns;
+
+ /* _mapClvToCns maps variable to the constraints in which
+ it is rw (it omits where it is ro) */
+ ClVarToConstraintSetMap _mapClvToCns;
+
+ /* track what edges correspond to which constraints
+ so we can update the constraint graph when
+ removing a constraint */
+ map<ClConstraint *, edge> _mapCnToEdge;
+
+ /* track what nodes correspond to which variables */
+ map<ClVariable, node> _mapVarToNode;
+
+ /* directed graph that mirrors the structure of
+ the relations of the added constraints */
+ graph G;
+
+ node_map<ClVariable> nodeToVar;
+};
+
+#define FDN_EOL LONG_MIN
+
+void ListPushOnto(list<FDNumber> *pl, ...);
+
+#endif
diff --git a/libs/cassowary/cassowary/ClFDVariable.h b/libs/cassowary/cassowary/ClFDVariable.h
new file mode 100644
index 0000000000..326b339459
--- /dev/null
+++ b/libs/cassowary/cassowary/ClFDVariable.h
@@ -0,0 +1,126 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClFDVariable.h
+
+#ifndef ClFDVariable_H
+#define ClFDVariable_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include <cstdio>
+#include <map>
+#include <string>
+#include <list>
+#include "Cassowary.h"
+#include "ClAbstractVariable.h"
+
+using std::map;
+using std::list;
+using std::string;
+
+class ClFDVariable : public ClAbstractVariable {
+public:
+ typedef ClAbstractVariable super;
+
+#if 0 /* GJB:FIXME:: */
+ ClFDVariable(string name, FDNumber Value) :
+ ClAbstractVariable(name),
+ _value(Value),
+ _fSet(true),
+ _desired_value(Value),
+ _plfdnInitialDomain(0)
+ { }
+#endif
+
+ ClFDVariable(string name, FDNumber Value, const list<FDNumber> &initial_domain) :
+ ClAbstractVariable(name),
+ _value(Value),
+ _fSet(true),
+ _desired_value(Value),
+ _plfdnInitialDomain(new list<FDNumber>())
+ {
+ *_plfdnInitialDomain = initial_domain;
+ }
+
+ virtual bool IsFDVariable() const
+ { return true; }
+
+ // Return true if this a variable known outside the solver.
+ // (We need to give such variables a Value after solving is complete.)
+ virtual bool IsExternal() const
+ { return true; }
+
+#ifndef CL_NO_IO
+ // Prints a semi-descriptive representation to the stream, using the
+ // name if there is one, and otherwise the hash number of this
+ // object.
+ // EXAMPLE
+ // [x:10.0] -- name = "x", Value = 10.0
+ virtual ostream &PrintOn(ostream &xo) const;
+#endif
+
+ // Return the current Value I hold.
+ Number Value() const
+ { return _value; }
+
+ // Round the Value to an integer and return it
+ int IntValue() const
+ { return _value; }
+
+ // change the Value held -- should *not* use this if the variable is
+ // in a solver -- instead use AddEditVar() and SuggestValue() interface
+ void SetValue(FDNumber Value)
+ { _value = Value; }
+
+ // permit overriding in subclasses in case something needs to be
+ // done when the Value is changed by the solver
+ // may be called when the Value hasn't actually changed -- just
+ // means the solver is setting the external variable
+ virtual void ChangeValue(FDNumber Value)
+ { _value = Value; }
+
+ virtual bool FIsSet()
+ { return _fSet; }
+
+ virtual void SetFIsSet(bool f)
+ { _fSet = f; }
+
+ virtual FDNumber DesiredValue() const
+ { return _desired_value; }
+
+ virtual const list<FDNumber> *PlfdnDomain() const
+ { return _plfdnInitialDomain; }
+
+protected:
+
+ // similar to SetValue -- see caveat above -- made private for now
+ // since it's probably the wrong thing and is too easy to invoke
+ FDNumber operator=(FDNumber Value)
+ { _value = Value; return Value; }
+
+ // Copy constructor left undefined since we want to
+ // outlaw passing by Value! Will get a link error if you
+ // try to use within ClFDVariable.c, compile-time error everywhere else
+ ClFDVariable(const ClFDVariable &);
+
+ FDNumber _value;
+
+ // has the _value been set? Used during solves.
+ bool _fSet;
+
+ FDNumber _desired_value;
+
+ list<FDNumber> *_plfdnInitialDomain;
+};
+
+#endif
diff --git a/libs/cassowary/cassowary/ClFloatVariable.h b/libs/cassowary/cassowary/ClFloatVariable.h
new file mode 100644
index 0000000000..4e58036ab7
--- /dev/null
+++ b/libs/cassowary/cassowary/ClFloatVariable.h
@@ -0,0 +1,119 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClFloatVariable.h
+
+#ifndef ClFloatVariable_H
+#define ClFloatVariable_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include <cstdio>
+#include <map>
+#include <string>
+#include "Cassowary.h"
+#include "ClAbstractVariable.h"
+
+using std::map;
+using std::string;
+
+class ClFloatVariable : public ClAbstractVariable {
+public:
+ typedef ClAbstractVariable super;
+
+ ClFloatVariable(string name, Number Value = 0.0) :
+ ClAbstractVariable(name),
+ _value(Value)
+ { }
+
+ ClFloatVariable(Number Value = 0.0) :
+ ClAbstractVariable(""),
+ _value(Value)
+ { }
+
+ ClFloatVariable(long number, char *prefix, Number Value = 0.0) :
+ ClAbstractVariable(number,prefix),
+ _value(Value)
+ { }
+
+ virtual bool IsFloatVariable() const
+ { return true; }
+
+ // Return true if this a dummy variable (used as a marker variable
+ // for required equality constraints). Such variables aren't
+ // allowed to enter the basis when pivoting.
+ virtual bool IsDummy() const
+ { return false; }
+
+ // Return true if this a variable known outside the solver.
+ // (We need to give such variables a Value after solving is complete.)
+ virtual bool IsExternal() const
+ { return true; }
+
+ // Return true if we can Pivot on this variable.
+ virtual bool IsPivotable() const
+ { return false; }
+
+ // Return true if this is a restricted (or slack) variable. Such
+ // variables are constrained to be non-negative and occur only
+ // internally to the simplex solver.
+ virtual bool IsRestricted() const
+ { return false; }
+
+#ifndef CL_NO_IO
+ // Prints a semi-descriptive representation to the stream, using the
+ // name if there is one, and otherwise the hash number of this
+ // object.
+ // EXAMPLE
+ // [x:10.0] -- name = "x", Value = 10.0
+ virtual ostream &PrintOn(ostream &xo) const;
+#endif
+
+ // Return the current Value I hold.
+ Number Value() const
+ { return _value; }
+
+ // Round the Value to an integer and return it
+ int IntValue() const
+ { return int(_value + 0.5); }
+
+ // change the Value held -- should *not* use this if the variable is
+ // in a solver -- instead use AddEditVar() and SuggestValue() interface
+ void SetValue(Number Value)
+ { _value = Value; }
+
+ // permit overriding in subclasses in case something needs to be
+ // done when the Value is changed by the solver
+ // may be called when the Value hasn't actually changed -- just
+ // means the solver is setting the external variable
+ virtual void ChangeValue(Number Value)
+ { _value = Value; }
+
+private:
+
+ // similar to SetValue -- see caveat above -- made private for now
+ // since it's probably the wrong thing and is too easy to invoke
+ Number operator=(Number Value)
+ { _value = Value; return Value; }
+
+ // Copy constructor left undefined since we want to
+ // outlaw passing by Value! Will get a link error if you
+ // try to use within ClFloatVariable.c, compile-time error everywhere else
+ ClFloatVariable(const ClFloatVariable &);
+
+ Number _value;
+
+};
+
+
+
+#endif
diff --git a/libs/cassowary/cassowary/ClLinearConstraint.h b/libs/cassowary/cassowary/ClLinearConstraint.h
new file mode 100644
index 0000000000..d657d1d73e
--- /dev/null
+++ b/libs/cassowary/cassowary/ClLinearConstraint.h
@@ -0,0 +1,61 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClLinearConstraint.h
+
+#ifndef ClLinearConstraint_H
+#define ClLinearConstraint_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+#include "ClConstraint.h"
+#include "ClLinearExpression.h"
+
+
+// Add the ClLinearExpression member variable needed for both
+// ClLinearEquation and ClLinearInequality
+class ClLinearConstraint : public ClConstraint {
+ private: typedef ClConstraint super;
+
+ public:
+
+ // Constructor
+ ClLinearConstraint(const ClLinearExpression &cle,
+ const ClStrength &strength = ClsRequired(),
+ double weight = 1.0) :
+ ClConstraint(strength, weight),
+ _expression(cle)
+ { }
+
+ virtual ~ClLinearConstraint() {}
+
+ // Return my linear Expression. (For linear equations, this
+ // constraint represents Expression=0; for linear inequalities it
+ // represents Expression>=0.)
+ ClLinearExpression Expression() const
+ { return _expression; }
+
+ // do not do this if *this is inside a solver
+ void ChangeConstant(Number constant)
+ { _expression.Set_constant(constant); }
+
+ protected:
+
+ ClLinearExpression _expression;
+
+ virtual void setExpression( const ClLinearExpression &expr)
+ { _expression = expr; }
+
+};
+
+#endif
diff --git a/libs/cassowary/cassowary/ClLinearEquation.h b/libs/cassowary/cassowary/ClLinearEquation.h
new file mode 100644
index 0000000000..a02b51d70b
--- /dev/null
+++ b/libs/cassowary/cassowary/ClLinearEquation.h
@@ -0,0 +1,74 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClLinearEquation.h
+
+#ifndef ClLinearEquation_H
+#define ClLinearEquation_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+#include "ClLinearConstraint.h"
+#include "ClLinearExpression.h"
+
+class ClStrength;
+class ClVariable;
+
+class ClLinearEquation : public ClLinearConstraint {
+ private: typedef ClLinearConstraint super;
+
+ public:
+ //// Constructors
+
+ // ClLinearEquation(expr,...) is expr == 0
+ ClLinearEquation(const ClLinearExpression &cle,
+ const ClStrength &strength = ClsRequired(),
+ double weight = 1.0) :
+ ClLinearConstraint(cle,strength, weight)
+ { }
+
+ // ClLinearEquation(var,expr,...) is var == expr
+ ClLinearEquation(ClVariable clv,
+ const ClLinearExpression &cle,
+ const ClStrength &strength = ClsRequired(),
+ double weight = 1.0) :
+ ClLinearConstraint(cle,strength,weight)
+ { _expression.AddVariable(clv,-1.0); }
+
+ // ClLinearEquation(expr,var,...) is var == expr
+ ClLinearEquation(const ClLinearExpression &cle,
+ ClVariable clv,
+ const ClStrength &strength = ClsRequired(),
+ double weight = 1.0) :
+ ClLinearConstraint(cle,strength,weight)
+ { _expression.AddVariable(clv,-1.0); }
+
+ // ClLinearEquation(expr,expr,...) is expr == expr
+ ClLinearEquation(const ClLinearExpression &cle1,
+ const ClLinearExpression &cle2,
+ const ClStrength &strength = ClsRequired(),
+ double weight = 1.0) :
+ ClLinearConstraint(cle1,strength,weight)
+ { _expression.AddExpression(cle2,-1.0); }
+
+#ifndef CL_NO_IO
+ virtual ostream &PrintOn(ostream &xo) const
+ { super::PrintOn(xo); xo << " = 0 )"; return xo; }
+#endif
+
+ virtual bool FIsSatisfied() const
+ { return (_expression.Evaluate() == 0); }
+
+};
+
+#endif
diff --git a/libs/cassowary/cassowary/ClLinearExpression.h b/libs/cassowary/cassowary/ClLinearExpression.h
new file mode 100644
index 0000000000..0a1df9c243
--- /dev/null
+++ b/libs/cassowary/cassowary/ClLinearExpression.h
@@ -0,0 +1,298 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClLinearExpression.h
+
+#ifndef ClLinearExpression_H
+#define ClLinearExpression_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+#include "debug.h"
+#include "ClVariable.h"
+#include "ClLinearExpression_fwd.h"
+
+class ClSimplexSolver;
+class ClTableau;
+class ClSymbolicWeight;
+
+ClLinearExpression &cleNil();
+
+template <class T>
+class ClGenericLinearExpression {
+ public:
+ typedef std::map<ClVariable,T> ClVarToCoeffMap;
+
+ // convert Number-s into ClLinearExpression-s
+ ClGenericLinearExpression(T num = 0.0);
+
+ // Convert from ClVariable to a ClLinearExpression
+ // this replaces ClVariable::asLinearExpression
+ ClGenericLinearExpression(ClVariable clv, T value = 1.0, T constant = 0.0);
+
+ // copy ctr
+ ClGenericLinearExpression(const ClGenericLinearExpression<T> &expr) :
+ _constant(expr._constant),
+ _terms(expr._terms)
+ { }
+
+ virtual ~ClGenericLinearExpression();
+
+ // Return a new linear expression formed by multiplying self by x.
+ // (Note that this result must be linear.)
+ ClGenericLinearExpression<T> Times(Number x) const;
+
+ // Return a new linear expression formed by multiplying self by x.
+ // (Note that this result must be linear.)
+ ClGenericLinearExpression<T> Times(const ClGenericLinearExpression<T> &expr) const;
+
+ // Return a new linear expression formed by adding x to self.
+ ClGenericLinearExpression<T> Plus(const ClGenericLinearExpression<T> &expr) const;
+
+ // Return a new linear expression formed by subtracting x from self.
+ ClGenericLinearExpression<T> Minus(const ClGenericLinearExpression<T> &expr) const;
+
+ // Return a new linear expression formed by dividing self by x.
+ // (Note that this result must be linear.)
+ ClGenericLinearExpression<T> Divide(Number x) const;
+
+
+
+ // Return a new linear expression formed by multiplying self by x.
+ // (Note that this result must be linear.)
+ ClGenericLinearExpression<T> *P_times(Number x) const
+ { return new ClGenericLinearExpression<T>(Times(x)); }
+
+ // Return a new linear expression formed by adding x to self.
+ ClGenericLinearExpression<T> *P_plus(const ClGenericLinearExpression<T> &expr) const
+ { return new ClGenericLinearExpression<T>(Plus(expr)); }
+
+ // Return a new linear expression formed by subtracting x from self.
+ ClGenericLinearExpression<T> *P_minus(const ClGenericLinearExpression<T> &expr) const
+ { return new ClGenericLinearExpression<T>(Minus(expr)); }
+
+ // Return a new linear expression formed by dividing self by x.
+ // (Note that this result must be linear.)
+ ClGenericLinearExpression<T> *P_divide(Number x) const
+ { return new ClGenericLinearExpression<T>(Divide(x)); }
+
+ // Return a new linear expression formed by dividing self by x.
+ // (Note that this result must be linear.)
+ ClGenericLinearExpression<T> Divide(const ClGenericLinearExpression<T> &expr) const;
+
+ // Return a new linear expression (aNumber/this). Since the result
+ // must be linear, this is permissible only if 'this' is a constant.
+ ClGenericLinearExpression<T> DivFrom(const ClGenericLinearExpression<T> &expr) const;
+
+ // Return a new linear expression (aNumber-this).
+ ClGenericLinearExpression<T> SubtractFrom(const ClGenericLinearExpression<T> &expr) const
+ { return expr.Minus(*this); }
+
+ // Add n*expr to this expression from another expression expr.
+ ClGenericLinearExpression<T> &AddExpression(const ClGenericLinearExpression<T> &expr,
+ Number n = 1.0);
+
+ // Add n*expr to this expression from another expression expr.
+ // Notify the solver if a variable is added or deleted from this
+ // expression.
+ ClGenericLinearExpression<T> &AddExpression(const ClGenericLinearExpression<T> &expr, Number n,
+ ClVariable subject,
+ ClTableau &solver);
+
+ // Add a term c*v to this expression. If the expression already
+ // contains a term involving v, Add c to the existing coefficient.
+ // If the new coefficient is approximately 0, delete v.
+ ClGenericLinearExpression<T> &AddVariable(ClVariable v, T c = 1.0);
+
+ // Add a term c*v to this expression. If the expression already
+ // contains a term involving v, Add c to the existing coefficient.
+ // If the new coefficient is approximately 0, delete v.
+ ClGenericLinearExpression<T> &setVariable(ClVariable v, T c)
+ {assert(c != 0.0); _terms[v] = c; return *this; }
+
+ // Add a term c*v to this expression. If the expression already
+ // contains a term involving v, Add c to the existing coefficient.
+ // If the new coefficient is approximately 0, delete v. Notify the
+ // solver if v appears or disappears from this expression.
+ ClGenericLinearExpression<T> &AddVariable(ClVariable v, T c,
+ ClVariable subject,
+ ClTableau &solver);
+
+ // Return a pivotable variable in this expression. (It is an error
+ // if this expression is constant -- signal ExCLInternalError in
+ // that case). Return NULL if no pivotable variables
+ ClVariable AnyPivotableVariable() const;
+
+ // Replace var with a symbolic expression expr that is equal to it.
+ // If a variable has been added to this expression that wasn't there
+ // before, or if a variable has been dropped from this expression
+ // because it now has a coefficient of 0, inform the solver.
+ // PRECONDITIONS:
+ // var occurs with a non-Zero coefficient in this expression.
+ void SubstituteOut(ClVariable v,
+ const ClGenericLinearExpression<T> &expr,
+ ClVariable subject,
+ ClTableau &solver);
+
+ // This linear expression currently represents the equation
+ // oldSubject=self. Destructively modify it so that it represents
+ // the equation NewSubject=self.
+ //
+ // Precondition: NewSubject currently has a nonzero coefficient in
+ // this expression.
+ //
+ // NOTES
+ // Suppose this expression is c + a*NewSubject + a1*v1 + ... + an*vn.
+ //
+ // Then the current equation is
+ // oldSubject = c + a*NewSubject + a1*v1 + ... + an*vn.
+ // The new equation will be
+ // NewSubject = -c/a + oldSubject/a - (a1/a)*v1 - ... - (an/a)*vn.
+ // Note that the term involving NewSubject has been dropped.
+ void ChangeSubject(ClVariable old_subject,
+ ClVariable new_subject);
+
+ // This linear expression currently represents the equation self=0. Destructively modify it so
+ // that subject=self represents an equivalent equation.
+ //
+ // Precondition: subject must be one of the variables in this expression.
+ // NOTES
+ // Suppose this expression is
+ // c + a*subject + a1*v1 + ... + an*vn
+ // representing
+ // c + a*subject + a1*v1 + ... + an*vn = 0
+ // The modified expression will be
+ // subject = -c/a - (a1/a)*v1 - ... - (an/a)*vn
+ // representing
+ // subject = -c/a - (a1/a)*v1 - ... - (an/a)*vn
+ //
+ // Note that the term involving subject has been dropped.
+ // Returns the reciprocal, so ChangeSubject can use it, too
+ T NewSubject(ClVariable subject);
+
+ // Return the value of the linear expression
+ // given the current assignments of values to contained variables
+ T Evaluate() const;
+
+ // Return the coefficient corresponding to variable var, i.e.,
+ // the 'ci' corresponding to the 'vi' that var is:
+ // v1*c1 + v2*c2 + .. + vn*cn + c
+ T CoefficientFor(ClVariable var) const
+ {
+ typename ClVarToCoeffMap::const_iterator it = _terms.find(var);
+ if (it != _terms.end())
+ return (*it).second;
+ return 0.0;
+ }
+
+ T Constant() const
+ { return _constant; }
+
+ void Set_constant(T c)
+ { _constant = c; }
+
+ const ClVarToCoeffMap &Terms() const
+ { return _terms; }
+
+ ClVarToCoeffMap &Terms()
+ { return _terms; }
+
+ void IncrementConstant(T c)
+ { _constant += c; }
+
+ bool IsConstant() const
+ { return _terms.size() == 0; }
+
+#ifndef CL_NO_IO
+ virtual ostream &PrintOn(ostream &xo) const;
+
+ friend ostream &operator<<(ostream &xo,const ClGenericLinearExpression<T> &cle)
+ { return cle.PrintOn(xo); }
+#endif
+
+ friend ClGenericLinearExpression<T> operator+(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return e1.Plus(e2); }
+
+ friend ClGenericLinearExpression<T> operator-(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return e1.Minus(e2); }
+
+ friend ClGenericLinearExpression<T> operator*(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return e1.Times(e2); }
+
+
+ friend ClGenericLinearExpression<T> operator/(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return e1.Divide(e2); }
+
+ // FIXGJB -- this may be wrong -- should test underlying expression for equality
+ friend bool operator==(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return &e1 == &e2; }
+
+ /// Named versions of the operator functions for ease of
+ /// wrapping, or expressing using prefix notation
+
+ friend ClGenericLinearExpression<T> Plus(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return e1.Plus(e2); }
+
+ friend ClGenericLinearExpression<T> Minus(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return e1.Minus(e2); }
+
+ friend ClGenericLinearExpression<T> Times(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return e1.Times(e2); }
+
+
+ friend ClGenericLinearExpression<T> *Divide(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return new ClGenericLinearExpression<T>(e1.Divide(e2)); }
+
+ friend ClGenericLinearExpression<T> *p_Plus(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return new ClGenericLinearExpression<T>(e1.Plus(e2)); }
+
+ friend ClGenericLinearExpression<T> *p_Minus(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return new ClGenericLinearExpression<T>(e1.Minus(e2)); }
+
+ friend ClGenericLinearExpression<T> *p_Times(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return new ClGenericLinearExpression<T>(e1.Times(e2)); }
+
+ friend ClGenericLinearExpression<T> *p_Divide(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return new ClGenericLinearExpression<T>(e1.Divide(e2)); }
+
+
+ // FIXGJB -- this may be wrong -- should test underlying expression for equality
+ friend bool FEquals(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return &e1 == &e2; }
+
+ ClGenericLinearExpression<T> &MultiplyMe(T x);
+
+ private:
+
+ T _constant;
+ ClVarToCoeffMap _terms;
+
+};
+
+typedef ClGenericLinearExpression<Number>::ClVarToCoeffMap ClVarToNumberMap;
+
+#endif
diff --git a/libs/cassowary/cassowary/ClLinearExpression_fwd.h b/libs/cassowary/cassowary/ClLinearExpression_fwd.h
new file mode 100644
index 0000000000..99b48557ec
--- /dev/null
+++ b/libs/cassowary/cassowary/ClLinearExpression_fwd.h
@@ -0,0 +1,26 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClLinearExpression.h
+
+#ifndef ClLinearExpression_fwd_H
+#define ClLinearExpression_fwd_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+
+template <class T> class ClGenericLinearExpression;
+typedef ClGenericLinearExpression<Number> ClLinearExpression;
+typedef ClLinearExpression* PClLinearExpression;
+
+#endif
diff --git a/libs/cassowary/cassowary/ClLinearInequality.h b/libs/cassowary/cassowary/ClLinearInequality.h
new file mode 100644
index 0000000000..017c4b819e
--- /dev/null
+++ b/libs/cassowary/cassowary/ClLinearInequality.h
@@ -0,0 +1,167 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClLinearInequality.h
+
+#ifndef ClLinearInequality_H
+#define ClLinearInequality_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "ClConstraint.h"
+#include "ClLinearConstraint.h"
+
+class ClVariable;
+
+class ClLinearInequality : public ClLinearConstraint {
+ private: typedef ClLinearConstraint super;
+
+ public:
+ //// Constructors
+ // ClLinearInequality(expr,...) is expr >= 0
+ ClLinearInequality(const ClLinearExpression &cle,
+ const ClStrength &strength = ClsRequired(),
+ double weight = 1.0) :
+ ClLinearConstraint(cle,strength, weight),
+ _fStrictInequality(false)
+ { }
+
+ // ClLinearInequality(var,OP,expr) is var >= expr
+ ClLinearInequality(const ClVariable clv,
+ enum ClCnRelation op,
+ const ClLinearExpression &cle,
+ const ClStrength &strength = ClsRequired(),
+ double weight = 1.0) :
+ ClLinearConstraint( cle, strength, weight),
+ _fStrictInequality(false)
+ {
+ if (op == cnGEQ || op == cnGT)
+ {
+ _expression.MultiplyMe(-1.0);
+ _expression.AddVariable(clv,1.0);
+ }
+ else if (op == cnLEQ || op == cnGEQ)
+ {
+ _expression.AddVariable(clv,-1.0);
+ }
+ else
+ {
+ throw ExCLEditMisuse("Cannot use that operator for ClLinearInequality objects");
+ }
+ if (op == cnLT || op == cnGT) {
+ _fStrictInequality = true;
+ }
+ }
+
+#ifdef FIXGJB_AMBIGUOUS
+ // ClLinearInequality(expr,OP,var) is var ?<>? expr
+ ClLinearInequality(const ClLinearExpression &cle,
+ enum ClCnRelation op,
+ const ClVariable clv,
+ const ClStrength &strength = ClsRequired(),
+ double weight = 1.0) :
+ ClLinearConstraint( cle, strength, weight),
+ _fStrictInequality(false)
+ {
+ if (op == cnLEQ || op == cnLT)
+ {
+ _expression.MultiplyMe(-1.0);
+ _expression.AddVariable(clv,1.0);
+ }
+ else if (op == cnGEQ || op == cnGT)
+ {
+ _expression.AddVariable(clv,-1.0);
+ }
+ if (op == cnLT || op == cnGT) {
+ _fStrictInequality = true;
+ }
+ }
+#endif
+
+ // ClLinearInequality(expr,OP,expr) is expr >= expr
+ ClLinearInequality(const ClLinearExpression &cle1,
+ enum ClCnRelation op,
+ const ClLinearExpression &cle2,
+ const ClStrength &strength = ClsRequired(),
+ double weight = 1.0) :
+ ClLinearConstraint( cle2, strength, weight),
+ _fStrictInequality(false)
+ {
+ if (op == cnGEQ || op == cnGT)
+ {
+ _expression.MultiplyMe(-1.0);
+ _expression.AddExpression(cle1);
+ }
+ else if (op == cnLEQ || op == cnLT)
+ {
+ _expression.AddExpression(cle1,-1.0);
+ }
+ if (op == cnLT || op == cnGT) {
+ _fStrictInequality = true;
+ }
+ }
+
+#ifdef FIXGJB_AMBIGUOUS
+ // ClLinearInequality(var,OP,var) is var ?<>? var
+ ClLinearInequality(const ClVariable clv1,
+ enum ClCnRelation op,
+ const ClVariable clv2,
+ const ClStrength &strength = ClsRequired(),
+ double weight = 1.0) :
+ ClLinearConstraint( clv2, strength, weight),
+ _fStrictInequality(false)
+ {
+ if (op == cnGEQ || op == cnGT)
+ {
+ _expression.MultiplyMe(-1.0);
+ _expression.AddVariable(clv1,1.0);
+ }
+ else if (op == cnLEQ || op == cnLT)
+ {
+ _expression.AddVariable(clv1,-1.0);
+ }
+ if (op == cnLT || op == cnGT) {
+ _fStrictInequality = true;
+ }
+ }
+#endif
+
+
+ // Return true if this is an inequality constraint and
+ // false if it is an equality constraint. The default is
+ // that it is not.
+ virtual bool IsInequality() const
+ { return true; }
+
+ virtual bool IsStrictInequality() const
+ { return _fStrictInequality; }
+
+#ifndef CL_NO_IO
+ virtual ostream &PrintOn(ostream &xo) const
+ { super::PrintOn(xo); xo << " >= 0 )"; return xo; }
+#endif
+
+ virtual bool FIsSatisfied() const
+ {
+ Number v = _expression.Evaluate();
+ if (_fStrictInequality)
+ return (v > 0);
+ else
+ return (v >= 0);
+ }
+
+ private:
+
+ bool _fStrictInequality;
+};
+
+#endif
diff --git a/libs/cassowary/cassowary/ClObjectiveVariable.h b/libs/cassowary/cassowary/ClObjectiveVariable.h
new file mode 100644
index 0000000000..664e2d65a4
--- /dev/null
+++ b/libs/cassowary/cassowary/ClObjectiveVariable.h
@@ -0,0 +1,63 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClObjectiveVariable.h
+
+#ifndef ClObjectiveVariable_H
+#define ClObjectiveVariable_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+#include "ClAbstractVariable.h"
+
+class ClTableau;
+class ClSimplexSolver;
+
+class ClObjectiveVariable : public ClAbstractVariable {
+protected:
+ friend class ClTableau;
+ friend class ClSimplexSolver;
+
+ ClObjectiveVariable(string name = "") :
+ ClAbstractVariable(name)
+ { }
+
+ ClObjectiveVariable(long number, char *prefix) :
+ ClAbstractVariable(number,prefix)
+ { }
+
+#ifndef CL_NO_IO
+ virtual ostream &PrintOn(ostream &xo) const
+ {
+ xo << "[" << Name() << ":obj]";
+ return xo;
+ }
+#endif
+
+ // We don't need to give such variables a Value after solving is complete.
+ virtual bool IsExternal() const
+ { return false; }
+
+ // Return true if we can Pivot on this variable.
+ virtual bool IsPivotable() const
+ { return false; }
+
+ // Return true if this is a restricted (or slack) variable. Such
+ // variables are constrained to be non-negative and occur only
+ // internally to the simplex solver.
+ virtual bool IsRestricted() const
+ { return false; }
+
+};
+
+#endif
diff --git a/libs/cassowary/cassowary/ClPoint.h b/libs/cassowary/cassowary/ClPoint.h
new file mode 100644
index 0000000000..15139aa73b
--- /dev/null
+++ b/libs/cassowary/cassowary/ClPoint.h
@@ -0,0 +1,74 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClPoint.h
+
+#ifndef ClPoint_H
+#define ClPoint_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+#include "ClVariable.h"
+
+// ClPoint is just a convenience class for pairs of
+// ClVariables -- often useful for coordinate pairs in 2-space
+class ClPoint {
+ public:
+ ClPoint(Number x, Number y)
+ : _clv_x(x), _clv_y(y)
+ { }
+
+ ClPoint()
+ { }
+
+ ClVariable X()
+ { return _clv_x; }
+
+ ClVariable Y()
+ { return _clv_y; }
+
+ const ClVariable X() const
+ { return _clv_x; }
+
+ const ClVariable Y() const
+ { return _clv_y; }
+
+ void SetXY(Number x, Number y)
+ { _clv_x.SetValue(x); _clv_y.SetValue(y); }
+
+ Number Xvalue() const
+ { return X().Value(); }
+
+ Number Yvalue() const
+ { return Y().Value(); }
+
+ private:
+ ClVariable _clv_x;
+ ClVariable _clv_y;
+
+#ifndef CL_NO_IO
+ friend ostream &operator<<(ostream &xo, const ClPoint &clp);
+#endif
+
+};
+
+#ifndef CL_NO_IO
+inline ostream &
+operator<<(ostream &xo, const ClPoint &clp)
+{
+ xo << "(" << clp._clv_x << ", " << clp._clv_y << ")";
+ return xo;
+}
+#endif
+
+#endif
diff --git a/libs/cassowary/cassowary/ClReader.h b/libs/cassowary/cassowary/ClReader.h
new file mode 100644
index 0000000000..59369d6ac2
--- /dev/null
+++ b/libs/cassowary/cassowary/ClReader.h
@@ -0,0 +1,117 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClReader.h
+// Original implementation contributed by Steve Wolfman
+// Subsequently largely revised by Greg J. Badros
+
+#ifndef CREADER_H
+#define CREADER_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include <string>
+#include <map>
+#include <algorithm>
+#include <iostream>
+#include "ClErrors.h"
+#include "ClVariable.h"
+#include "ClStrength.h"
+#include "ClLinearExpression_fwd.h"
+
+using std::string;
+using std::istream;
+
+class ClConstraint;
+
+class ClVarLookupFunction : public std::unary_function<const string &,ClVariable *> {
+public:
+ virtual ClVariable *operator()(const string &) const { return &clvNil; }
+};
+
+
+// Attempts to read a constraint of input stream in
+// Returns constraint (freshly allocated, client responsibility to deallocate)
+// if succesful. Otherwise, returns 0.
+ClConstraint *PcnParseConstraint(istream &xi, const ClVarLookupFunction &lookup_func,
+ const ClStrength &strength = ClsRequired());
+
+class ClVarLookupInMap : public ClVarLookupFunction {
+public:
+ ClVarLookupInMap(StringToVarMap *pmapVars, bool fAutoCreate)
+ : _pmapVars(pmapVars), _fAutoCreate(fAutoCreate) { }
+
+ ClVariable *operator()(const string &str) const
+ {
+ if (!_pmapVars)
+ return &clvNil;
+ StringToVarMap &_mapVars = *_pmapVars;
+ StringToVarMap::iterator it = _mapVars.find(str);
+ if (it != _mapVars.end()) {
+ return &it->second;
+ } else if (_fAutoCreate) {
+ // save the old symbol table, if any
+ StringToVarMap *pmapOld = ClVariable::VarMap();
+ // and set it to this one temporarily
+ ClVariable::SetVarMap(&_mapVars);
+ ClVariable *pclv = new ClVariable(str);
+ // now switch it back
+ ClVariable::SetVarMap(pmapOld);
+ return pclv;
+ } else {
+ return &clvNil;
+ }
+ }
+private:
+ StringToVarMap *_pmapVars;
+ bool _fAutoCreate;
+};
+
+
+/* the "yyerror" function */
+void clerror(const char *sz);
+
+struct ClParseData {
+ ClParseData(istream &xi, const ClVarLookupFunction &lookup_func)
+ : _xi(xi), _lookup_func(lookup_func) { }
+
+ ClConstraint *Pcn() { return _pcn; }
+
+ ClVarSet _readOnlyVarsSoFar;
+
+ istream & _xi;
+ ClConstraint * _pcn;
+ const ClVarLookupFunction &_lookup_func;
+};
+
+
+inline
+const ClStrength
+&ClsFromSz(const char *sz)
+{
+ const ClStrength *pcls = &ClsRequired();
+ double n1, n2, n3;
+ if (strcmp("required",sz) == 0)
+ ; /* initialized to ClsRequired, above */
+ else if (strcasecmp("strong",sz) == 0) { pcls = &ClsStrong(); }
+ else if (strcasecmp("medium",sz) == 0) { pcls = &ClsMedium(); }
+ else if (strcasecmp("weak",sz) == 0) { pcls = &ClsWeak(); }
+ else if (sscanf(sz,"(%lf,%lf,%lf)",&n1,&n2,&n3) == 3) {
+ pcls = new ClStrength("parsed",n1,n2,n3);
+ } else {
+ throw ExCLParseErrorMisc("Error parsing strength");
+ }
+ return *pcls;
+}
+
+
+#endif
diff --git a/libs/cassowary/cassowary/ClSimplexSolver.h b/libs/cassowary/cassowary/ClSimplexSolver.h
new file mode 100644
index 0000000000..c187992728
--- /dev/null
+++ b/libs/cassowary/cassowary/ClSimplexSolver.h
@@ -0,0 +1,588 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClSimplexSolver.h
+
+#ifndef ClSimplexSolver_H
+#define ClSimplexSolver_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include <stack>
+#include <list>
+#include <iostream>
+#include "Cassowary.h"
+#include "ClSolver.h"
+#include "ClTableau.h"
+#include "ClLinearInequality.h"
+#include "ClStrength.h"
+#include "ClStayConstraint.h"
+#include "ClEditConstraint.h"
+#include "ClSlackVariable.h"
+#include "ClObjectiveVariable.h"
+#include "ClErrors.h"
+#include "ClTypedefs.h"
+
+using std::list;
+using std::stack;
+using std::ostream;
+
+class ClVariable;
+class ClPoint;
+class ExCLRequiredFailureWithExplanation;
+
+
+// ClSimplexSolver encapsulates the solving behaviour
+// of the cassowary algorithm
+class ClSimplexSolver : public ClSolver, public ClTableau {
+ protected:
+ class ClEditInfo;
+ typedef list<ClEditInfo *> ClEditInfoList;
+
+ ClEditInfo *PEditInfoFromClv(ClVariable clv) {
+ ClEditInfoList::iterator it = _editInfoList.begin();
+ for (; it != _editInfoList.end(); ++it) {
+ ClEditInfo *pei = (*it);
+ if (pei->_clv == clv)
+ return pei;
+ }
+ return 0;
+ }
+
+ public:
+
+ // Constructor
+ ClSimplexSolver() :
+ ClSolver(),
+ _objective(ClVariable(new ClObjectiveVariable("Z"))),
+ _slackCounter(0),
+ _artificialCounter(0),
+#ifdef CL_FIND_LEAK
+ _cArtificialVarsDeleted(0),
+#endif
+ _dummyCounter(0),
+ _epsilon(1e-8),
+ _fResetStayConstantsAutomatically(true),
+ _fNeedsSolving(false),
+ _fExplainFailure(false),
+ _pfnResolveCallback(0),
+ _pfnCnSatCallback(0)
+ {
+ _rows[_objective] = new ClLinearExpression();
+ // start out with no edit variables
+ _stkCedcns.push(0);
+#ifdef CL_TRACE
+ std::cerr << "objective row new@ " << _rows[_objective] << std::endl;
+#endif
+ }
+
+ virtual ~ClSimplexSolver();
+
+ // Add constraints so that lower<=var<=upper. (nil means no bound.)
+ ClSimplexSolver &AddLowerBound(ClVariable v, Number lower)
+ {
+ ClLinearInequality *pcn = new ClLinearInequality(ClLinearExpression(v - lower));
+ return AddConstraint(pcn);
+ }
+ ClSimplexSolver &AddUpperBound(ClVariable v, Number upper)
+ {
+ ClLinearInequality *pcn = new ClLinearInequality(ClLinearExpression(upper - v));
+ return AddConstraint(pcn);
+ }
+ ClSimplexSolver &AddBounds(ClVariable v, Number lower, Number upper)
+ { AddLowerBound(v,lower); AddUpperBound(v,upper); return *this; }
+
+ // Add the constraint cn to the tableau
+ ClSimplexSolver &AddConstraint(ClConstraint *const pcn);
+
+#ifndef CL_NO_DEPRECATED
+ // Deprecated! --02/19/99 gjb
+ ClSimplexSolver &AddConstraint(ClConstraint &cn)
+ { return AddConstraint(&cn); }
+#endif
+
+ // Add an edit constraint for "v" with given strength
+ ClSimplexSolver &AddEditVar(const ClVariable v, const ClStrength &strength = ClsStrong(),
+ double weight = 1.0 )
+ {
+ ClEditConstraint *pedit = new ClEditConstraint(v, strength, weight);
+ return AddConstraint(pedit);
+ }
+
+ ClSimplexSolver &RemoveEditVar(ClVariable v)
+ {
+ ClEditInfo *pcei = PEditInfoFromClv(v);
+ if (!pcei) {
+ throw ExCLEditMisuse("Removing edit variable that was not found");
+ }
+ ClConstraint *pcnEdit = pcei->_pconstraint;
+ RemoveConstraint(pcnEdit);
+ delete pcnEdit;
+ return *this;
+ }
+
+ // BeginEdit() should be called before sending
+ // Resolve() messages, after adding the appropriate edit variables
+ ClSimplexSolver &BeginEdit()
+ {
+ if (_editInfoList.size() == 0) {
+ throw ExCLEditMisuse("BeginEdit called, but no edit variable");
+ }
+ // may later want to do more in here
+ _infeasibleRows.clear();
+ ResetStayConstants();
+ _stkCedcns.push(_editInfoList.size());
+ return *this;
+ }
+
+ // EndEdit should be called after editing has finished
+ // for now, it just removes edit variables added from before the last BeginEdit
+ ClSimplexSolver &EndEdit()
+ {
+ if (_editInfoList.size() == 0)
+ throw ExCLEditMisuse("EndEdit called but no edit variables");
+ Resolve();
+ _stkCedcns.pop();
+ RemoveEditVarsTo(_stkCedcns.top());
+ // may later want to do more in here
+ return *this;
+ }
+
+ // RemoveAllEditVars() just eliminates all the edit constraints
+ // that were added
+ ClSimplexSolver &RemoveAllEditVars() { RemoveEditVarsTo(0); return *this; }
+
+ // remove the last added edit vars to leave only n edit vars left
+ ClSimplexSolver &RemoveEditVarsTo(unsigned int n);
+
+ int numEditVars() const
+ { return _editInfoList.size(); }
+
+ // Add weak stays to the x and y parts of each point. These have
+ // increasing weights so that the solver will try to satisfy the x
+ // and y stays on the same point, rather than the x stay on one and
+ // the y stay on another.
+ ClSimplexSolver &AddPointStays(const vector<const ClPoint *> &listOfPoints,
+ const ClStrength &strength = ClsWeak());
+
+ ClSimplexSolver &AddPointStay(const ClVariable vx, const ClVariable vy,
+ const ClStrength &strength = ClsWeak(),
+ double weight = 1.0)
+ { AddStay(vx,strength,weight); AddStay(vy,strength,weight); return *this; }
+
+ ClSimplexSolver &AddPointStay(const ClPoint &clp,
+ const ClStrength &strength = ClsWeak(),
+ double weight = 1.0);
+
+
+ // Add a stay of the given strength (default to weak) of v to the tableau
+ ClSimplexSolver &AddStay(const ClVariable v,
+ const ClStrength &strength = ClsWeak(), double weight = 1.0 )
+ {
+ ClStayConstraint *pcn = new ClStayConstraint(v,strength,weight);
+ return AddConstraint(pcn);
+ }
+
+ // Remove the constraint cn from the tableau
+ // Also remove any error variable associated with cn
+ ClSimplexSolver &RemoveConstraint(ClConstraint *const pcn)
+ { RemoveConstraintInternal(pcn); pcn->removedFrom(*this); return *this; }
+
+#ifndef CL_NO_DEPRECATED
+ // Deprecated! --02/19/99 gjb
+ ClSimplexSolver &RemoveConstraint(ClConstraint &cn)
+ { return RemoveConstraint(&cn); }
+#endif
+
+
+ // Re-initialize this solver from the original constraints, thus
+ // getting rid of any accumulated numerical problems. (Actually, we
+ // haven't definitely observed any such problems yet)
+ void Reset();
+
+ // Re-solve the current collection of constraints, given the new
+ // values for the edit variables that have already been
+ // suggested (see SuggestValue() method)
+ // This is not guaranteed to work if you remove an edit constraint
+ // from the middle of the edit constraints you added
+ // (e.g., edit A, edit B, edit C, remove B -> this will fail!)
+ // DEPRECATED
+ void Resolve();
+
+ // Re-solve the current collection of constraints for new values for
+ // the constants of the edit variables.
+ // This is implemented in terms of SuggestValue-s, and is
+ // less efficient than that more natural interface
+ void Resolve(const vector<Number> &newEditConstants);
+
+ // Convenience function for Resolve-s of two variables
+ void Resolve(Number x, Number y)
+ {
+ vector<Number> vals;
+ vals.push_back(x);
+ vals.push_back(y);
+ Resolve(vals);
+ }
+
+ // Suggest a new value for an edit variable
+ // the variable needs to be added as an edit variable
+ // and BeginEdit() needs to be called before this is called.
+ // The tableau will not be solved completely until
+ // after Resolve() has been called
+ ClSimplexSolver &SuggestValue(ClVariable v, Number x);
+
+ // Set and check whether or not the solver will attempt to compile
+ // an explanation of failure when a required constraint conflicts
+ // with another required constraint
+ ClSimplexSolver &SetExplaining(bool f)
+ { _fExplainFailure = f; return *this; }
+
+ bool FIsExplaining() const
+ { return _fExplainFailure; }
+
+ // If autosolving has been turned off, client code needs
+ // to explicitly call solve() before accessing variables
+ // values
+ ClSimplexSolver &Solve()
+ {
+#ifdef CL_SOLVER_CHECK_INTEGRITY
+ AssertValid();
+#endif
+ if (_fNeedsSolving)
+ {
+ Optimize(_objective);
+ SetExternalVariables();
+#ifdef CL_TRACE_VERBOSE
+ std::cerr << "Manual solve actually solving." << std::endl;
+#endif
+ }
+ return *this;
+ }
+
+ ClSimplexSolver &SetEditedValue(ClVariable v, double n)
+ {
+ if (!FContainsVariable(v))
+ {
+ ChangeClv(v,n);
+ return *this;
+ }
+
+ if (!ClApprox(n, v.Value()))
+ {
+ AddEditVar(v);
+ BeginEdit();
+ SuggestValue(v,n);
+ EndEdit();
+ }
+ return *this;
+ }
+
+ // Solver contains the variable if it's in either the columns
+ // list or the rows list
+ bool FContainsVariable(const ClVariable v)
+ { return ColumnsHasKey(v) || RowExpression(v); }
+
+ ClSimplexSolver &AddVar(const ClVariable v)
+ { if (!FContainsVariable(v))
+ {
+ AddStay(v);
+#ifdef CL_TRACE
+ std::cerr << "added initial stay on " << v << std::endl;
+#endif
+ }
+ return *this; }
+
+ typedef void (*PfnResolveCallback)(ClSimplexSolver *psolver);
+
+ void SetResolveCallback(PfnResolveCallback pfn)
+ { _pfnResolveCallback = pfn; }
+
+ typedef void (*PfnCnSatCallback)(ClSimplexSolver *psolver,
+ ClConstraint *pcn, bool fSatisfied);
+
+ void SetCnSatCallback(PfnCnSatCallback pfn)
+ { _pfnCnSatCallback = pfn; }
+
+#ifndef CL_NO_IO
+ friend ostream &operator<<(ostream &xo, const ClSimplexSolver &tableau);
+
+ ostream &PrintOn(ostream &xo) const;
+
+ ostream &PrintInternalInfo(ostream &xo) const;
+
+ ostream &PrintOnVerbose(ostream &xo) const
+ { PrintOn(xo); PrintInternalInfo(xo); xo << std::endl; return xo; }
+
+#endif
+
+ const ClConstraintToVarMap &ConstraintMap() const
+ { return _markerVars; }
+
+ const ClVarToConstraintMap &MarkerMap() const
+ { return _constraintsMarked; }
+
+ bool FIsConstraintSatisfied(const ClConstraint *const pcn) const;
+
+ // DEPRECATED
+ bool FIsConstraintSatisfied(const ClConstraint &pcn) const
+ { return FIsConstraintSatisfied(&pcn); }
+
+ // re-set all the external variables to their current values
+ // most importantly, this re-calls all the ChangeClv callbacks
+ // (which might be used to copy the ClVariable's value to another
+ // variable)
+ void UpdateExternalVariables()
+ { SetExternalVariables(); }
+
+ // A. Beurive' Tue Jul 6 17:05:39 CEST 1999
+ void ChangeStrengthAndWeight(ClConstraint *pcn, const ClStrength &strength, double weight);
+ void ChangeStrength(ClConstraint *pcn, const ClStrength &strength);
+ void ChangeWeight(ClConstraint *pcn, double weight);
+ // void DisplayObjective();
+
+ // Each of the non-required stays will be represented by an equation
+ // of the form
+ // v = c + eplus - eminus
+ // where v is the variable with the stay, c is the previous value of
+ // v, and eplus and eminus are slack variables that hold the error
+ // in satisfying the stay constraint. We are about to change
+ // something, and we want to fix the constants in the equations
+ // representing the stays. If both eplus and eminus are nonbasic
+ // they have value 0 in the current solution, meaning the previous
+ // stay was exactly satisfied. In this case nothing needs to be
+ // changed. Otherwise one of them is basic, and the other must
+ // occur only in the Expression for that basic error variable.
+ // Reset the Constant in this Expression to 0.
+ void ResetStayConstants();
+
+ ClSimplexSolver &SetAutoResetStayConstants(bool f)
+ { _fResetStayConstantsAutomatically = f; if (f) ResetStayConstants(); return *this; }
+
+ bool FIsAutoResetStayConstants() const
+ { return _fResetStayConstantsAutomatically; }
+
+ protected:
+
+ // ClEditInfo is a privately-used class
+ // that just wraps a constraint, its positive and negative
+ // error variables, and its prior edit Constant.
+ // It is used as values in _editInfoList, and replaces
+ // the parallel vectors of error variables and previous edit
+ // constants from the smalltalk version of the code.
+ class ClEditInfo {
+ friend class ClSimplexSolver;
+ public:
+
+ // These instances own none of the pointers;
+ // the tableau row (the Expression) owns the peplus, peminus,
+ // and AddEditVar/RemoveEditVar pair or the client code owns
+ // the constraint object
+ ClEditInfo(ClVariable clv,
+ ClEditConstraint *pconstraint,
+ ClVariable eplus, ClVariable eminus,
+ Number prevEditConstant)
+ :_clv(clv),
+ _pconstraint(pconstraint),
+ _clvEditPlus(eplus), _clvEditMinus(eminus),
+ _prevEditConstant(prevEditConstant)
+ { }
+
+ ~ClEditInfo()
+ { }
+
+ ostream &PrintOn(ostream &xo) const
+ { xo << _clv << " -> [" << _clvEditPlus << ", " << _clvEditMinus << "]("
+ << _prevEditConstant << ")@" << " -- "
+ << *_pconstraint;
+ return xo; }
+
+ friend ostream &operator<<(ostream &xo, const ClEditInfo &cei)
+ { return cei.PrintOn(xo); }
+
+ private:
+ ClVariable _clv;
+ ClConstraint *_pconstraint;
+ ClVariable _clvEditPlus;
+ ClVariable _clvEditMinus;
+ Number _prevEditConstant;
+ };
+
+ // Add the constraint expr=0 to the inequality tableau using an
+ // artificial variable. To do this, create an artificial variable
+ // av and Add av=expr to the inequality tableau, then make av be 0.
+ // (Raise an exception if we can't attain av=0.)
+ // (Raise an exception if we can't attain av=0.) If the Add fails,
+ // prepare an explanation in e that describes why it failed (note
+ // that an empty explanation is considered to mean the explanation
+ // encompasses all active constraints.
+ bool AddWithArtificialVariable(ClLinearExpression &pexpr,
+ ExCLRequiredFailureWithExplanation &e);
+
+ // Using the given equation (av = cle) build an explanation which
+ // implicates all constraints used to construct the equation. That
+ // is, everything for which the variables in the equation are markers.
+ // Thanks to Steve Wolfman for the implementation of the explanation feature
+ void BuildExplanation(ExCLRequiredFailureWithExplanation & e,
+ ClVariable av,
+ const ClLinearExpression * pcle);
+
+ // We are trying to Add the constraint expr=0 to the appropriate
+ // tableau. Try to Add expr directly to the tableax without
+ // creating an artificial variable. Return true if successful and
+ // false if not.
+ bool TryAddingDirectly(ClLinearExpression &pexpr);
+
+ // We are trying to Add the constraint expr=0 to the tableaux. Try
+ // to choose a subject (a variable to become basic) from among the
+ // current variables in expr. If expr contains any unrestricted
+ // variables, then we must choose an unrestricted variable as the
+ // subject. Also, if the subject is new to the solver we won't have
+ // to do any substitutions, so we prefer new variables to ones that
+ // are currently noted as parametric. If expr contains only
+ // restricted variables, if there is a restricted variable with a
+ // negative coefficient that is new to the solver we can make that
+ // the subject. Otherwise we can't find a subject, so return nil.
+ // (In this last case we have to Add an artificial variable and use
+ // that variable as the subject -- this is done outside this method
+ // though.)
+ //
+ // Note: in checking for variables that are new to the solver, we
+ // ignore whether a variable occurs in the objective function, since
+ // new slack variables are added to the objective function by
+ // 'NewExpression:', which is called before this method.
+ ClVariable ChooseSubject(ClLinearExpression &pexpr);
+
+ // Each of the non-required edits will be represented by an equation
+ // of the form
+ // v = c + eplus - eminus
+ // where v is the variable with the edit, c is the previous edit
+ // value, and eplus and eminus are slack variables that hold the
+ // error in satisfying the edit constraint. We are about to change
+ // something, and we want to fix the constants in the equations
+ // representing the edit constraints. If one of eplus and eminus is
+ // basic, the other must occur only in the Expression for that basic
+ // error variable. (They can't both be basic.) Fix the Constant in
+ // this Expression. Otherwise they are both nonbasic. Find all of
+ // the expressions in which they occur, and fix the constants in
+ // those. See the UIST paper for details.
+ // (This comment was for resetEditConstants(), but that is now
+ // gone since it was part of the screwey vector-based interface
+ // to resolveing. --02/15/99 gjb)
+ void DeltaEditConstant(Number delta, ClVariable pv1, ClVariable pv2);
+
+ // We have set new values for the constants in the edit constraints.
+ // Re-Optimize using the dual simplex algorithm.
+ void DualOptimize();
+
+ // Make a new linear Expression representing the constraint cn,
+ // replacing any basic variables with their defining expressions.
+ // Normalize if necessary so that the Constant is non-negative. If
+ // the constraint is non-required give its error variables an
+ // appropriate weight in the objective function.
+ ClLinearExpression *NewExpression(const ClConstraint *pcn,
+ /* output to */
+ ClVariable &clvEplus,
+ ClVariable &clvEminus,
+ Number &prevEConstant);
+
+ // Minimize the value of the objective. (The tableau should already
+ // be feasible.)
+ void Optimize(ClVariable zVar);
+
+ // Do a Pivot. Move entryVar into the basis (i.e. make it a basic variable),
+ // and move exitVar out of the basis (i.e., make it a parametric variable)
+ void Pivot(ClVariable entryVar, ClVariable exitVar);
+
+ // Set the external variables known to this solver to their appropriate values.
+ // Set each external basic variable to its value, and set each
+ // external parametric variable to 0. (It isn't clear that we will
+ // ever have external parametric variables -- every external
+ // variable should either have a stay on it, or have an equation
+ // that defines it in terms of other external variables that do have
+ // stays. For the moment I'll put this in though.) Variables that
+ // are internal to the solver don't actually store values -- their
+ // values are just implicit in the tableu -- so we don't need to set
+ // them.
+ void SetExternalVariables();
+
+ // this gets called by RemoveConstraint and by AddConstraint when the
+ // contraint we're trying to Add is inconsistent
+ ClSimplexSolver &RemoveConstraintInternal(const ClConstraint *const pcn);
+
+ void ChangeClv(ClVariable clv, Number n) {
+ clv.ChangeValue(n);
+ if (_pfnChangeClvCallback)
+ _pfnChangeClvCallback(&clv,this);
+ }
+
+ /// instance variables
+
+ // the arrays of positive and negative error vars for the stay constraints
+ // (need both positive and negative since they have only non-negative values)
+ ClVarVector _stayMinusErrorVars;
+ ClVarVector _stayPlusErrorVars;
+
+ // give error variables for a non required constraint,
+ // maps to ClSlackVariable-s
+ ClConstraintToVarSetMap _errorVars;
+
+ // Return a lookup table giving the marker variable for each
+ // constraint (used when deleting a constraint).
+ ClConstraintToVarMap _markerVars;
+
+ // Reverse of the above-- a lookup table giving the constraint
+ // for each marker variable (used when building failure explanations)
+ ClVarToConstraintMap _constraintsMarked;
+
+ ClVariable _objective;
+
+ // Map edit variables to their constraints, errors, and prior
+ // values
+ ClEditInfoList _editInfoList;
+
+ int _slackCounter;
+ int _artificialCounter;
+#ifdef CL_FIND_LEAK
+ int _cArtificialVarsDeleted;
+#endif
+ int _dummyCounter;
+ const double _epsilon;
+
+ bool _fResetStayConstantsAutomatically;
+ bool _fNeedsSolving;
+ bool _fExplainFailure;
+
+ PfnResolveCallback _pfnResolveCallback;
+ PfnCnSatCallback _pfnCnSatCallback;
+
+ // C-style extension mechanism so I
+ // don't have to wrap ScwmClSolver separately
+ void *_pv;
+
+ // a stack of the number of edit constraints
+ // that existed at the prior BeginEdit.
+ // an EndEdit needs to pop off the top value,
+ // then remove constraints to get down
+ // to the # of constraints as in _stkCedcns.top()
+ stack<int> _stkCedcns;
+
+
+#ifndef CL_NO_IO
+
+friend ostream &PrintTo(ostream &xo, const ClSimplexSolver::ClEditInfoList &listPEditInfo);
+friend ostream &operator<<(ostream &xo, const ClSimplexSolver::ClEditInfoList &listPEditInfo);
+
+#endif
+
+};
+
+#endif // ClSimplexSolver_H
diff --git a/libs/cassowary/cassowary/ClSlackVariable.h b/libs/cassowary/cassowary/ClSlackVariable.h
new file mode 100644
index 0000000000..ca116702e9
--- /dev/null
+++ b/libs/cassowary/cassowary/ClSlackVariable.h
@@ -0,0 +1,75 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClSlackVariable.h
+
+#ifndef ClSlackVariable_H
+#define ClSlackVariable_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+#include "ClAbstractVariable.h"
+
+class ClTableau;
+class ClSimplexSolver;
+
+
+class ClSlackVariable : public ClAbstractVariable {
+public:
+#ifdef CL_FIND_LEAK
+ ~ClSlackVariable() { --cSlackVariables; };
+
+ static long cSlackVariables;
+#endif
+
+protected:
+ friend class ClTableau;
+ friend class ClSimplexSolver;
+
+ ClSlackVariable(string Name = "") :
+ ClAbstractVariable(Name)
+ {
+#ifdef CL_FIND_LEAK
+ ++cSlackVariables;
+#endif
+ }
+
+ ClSlackVariable(long number, char *prefix) :
+ ClAbstractVariable(number,prefix)
+ {
+#ifdef CL_FIND_LEAK
+ ++cSlackVariables;
+#endif
+ }
+
+#ifndef CL_NO_IO
+ virtual ostream &PrintOn(ostream &xo) const
+ {
+ xo << "[" << Name() << ":slack]";
+ return xo;
+ }
+#endif
+
+ virtual bool IsExternal() const
+ { return false; }
+
+ virtual bool IsPivotable() const
+ { return true; }
+
+ virtual bool IsRestricted() const
+ { return true; }
+
+};
+
+
+#endif
diff --git a/libs/cassowary/cassowary/ClSolver.h b/libs/cassowary/cassowary/ClSolver.h
new file mode 100644
index 0000000000..16e798d491
--- /dev/null
+++ b/libs/cassowary/cassowary/ClSolver.h
@@ -0,0 +1,167 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClSolver.h
+
+#ifndef ClSolver_H
+#define ClSolver_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+#include "ClErrors.h"
+#include "ClTypedefs.h"
+#include <list>
+#include <iostream>
+
+using std::list;
+using std::ostream;
+
+class ClVariable;
+
+// ClSolver is an abstract base class
+class ClSolver {
+ public:
+
+ ClSolver() : _pv(0), _fAutosolve(true), _pfnChangeClvCallback(0) { }
+
+ virtual ~ClSolver()
+ { }
+
+ // Add the constraint cn to the solver
+ virtual ClSolver &AddConstraint(ClConstraint *const pcn) = 0;
+
+ // Remove the constraint cn from the solver
+ virtual ClSolver &RemoveConstraint(ClConstraint *const pcn) = 0;
+
+ // Same as above, but returns false if the constraint cannot be solved
+ // (i.e., the resulting system would be unsatisfiable)
+ // The above function "AddConstraint" throws an exception in that case
+ // which may be inconvenient
+ virtual bool AddConstraintNoException(ClConstraint *const pcn)
+ {
+ try {
+ AddConstraint(pcn);
+ return true;
+ }
+ catch (const ExCLRequiredFailure &e)
+ { return false; }
+ catch (const ExCLTooDifficult &e)
+ { return false; }
+ }
+
+#ifndef CL_NO_DEPRECATED
+ // Deprecated --02/22/99 gjb
+ bool AddConstraintNoException(ClConstraint &cn)
+ { return AddConstraintNoException(&cn); }
+#endif
+
+ virtual bool RemoveConstraintNoException(ClConstraint *const pcn)
+ {
+ try {
+ RemoveConstraint(pcn);
+ return true;
+ }
+ catch (const ExCLConstraintNotFound &e)
+ { return false; }
+ }
+
+#ifndef CL_NO_DEPRECATED
+ // Deprecated --02/22/99 gjb
+ bool RemoveConstraintNoException(ClConstraint &cn)
+ { return RemoveConstraintNoException(&cn); }
+#endif
+
+
+ virtual ClSolver &Solve()
+ { assert(false); return *this; }
+
+ virtual bool SolveNoException()
+ {
+ try {
+ Solve();
+ return true;
+ }
+ catch (const ExCLTooDifficult &e)
+ { return false; }
+ catch (const ExCLRequiredFailure &e)
+ { return false; }
+ }
+
+
+ virtual void Resolve()
+ { assert(false); }
+
+ void SetPv(void *pv)
+ { _pv = pv; }
+
+ void *Pv() const
+ { return _pv; }
+
+ typedef void (*PfnChangeClvCallback)(ClVariable *pclv, ClSolver *psolver);
+
+ void SetChangeClvCallback(PfnChangeClvCallback pfn)
+ { _pfnChangeClvCallback = pfn; }
+
+ // Control whether optimization and setting of external variables
+ // is done automatically or not. By default it is done
+ // automatically and solve() never needs to be explicitly
+ // called by client code; if SetAutosolve is put to false,
+ // then solve() needs to be invoked explicitly before using
+ // variables' values
+ // (Turning off autosolve while adding lots and lots of
+ // constraints [ala the addDel test in ClTests] saved
+ // about 20% in runtime, from 68sec to 54sec for 900 constraints,
+ // with 126 failed adds)
+ ClSolver &SetAutosolve(bool f)
+ { _fAutosolve = f; if (f) Solve(); return *this; }
+
+ // Tell whether we are autosolving
+ bool FIsAutosolving() const
+ { return _fAutosolve; }
+
+
+#ifndef CL_NO_IO
+ friend ostream &operator<<(ostream &xo, const ClSolver &solver);
+
+ virtual ostream &PrintOn(ostream &xo) const = 0;
+
+#endif
+
+ protected:
+
+ // C-style extension mechanism so I
+ // don't have to wrap ScwmClSolver separately
+ void *_pv;
+
+ bool _fAutosolve;
+
+ PfnChangeClvCallback _pfnChangeClvCallback;
+};
+
+
+#ifndef CL_NO_IO
+ostream &PrintTo(ostream &xo, const ClVarVector &varlist);
+ostream &operator<<(ostream &xo, const ClVarVector &varlist);
+
+ostream &PrintTo(ostream &xo, const ClConstraintToVarSetMap &mapCnToVarSet);
+ostream &operator<<(ostream &xo, const ClConstraintToVarSetMap &mapCnToVarSet);
+
+ostream &PrintTo(ostream &xo, const ClConstraintSet &setCn);
+ostream &operator<<(ostream &xo, const ClConstraintSet &setCn);
+
+ostream &PrintTo(ostream &xo, const list<FDNumber> &listFDN);
+ostream &operator<<(ostream &xo, const list<FDNumber> &listFDN);
+
+#endif
+
+#endif
diff --git a/libs/cassowary/cassowary/ClStayConstraint.h b/libs/cassowary/cassowary/ClStayConstraint.h
new file mode 100644
index 0000000000..f009731b09
--- /dev/null
+++ b/libs/cassowary/cassowary/ClStayConstraint.h
@@ -0,0 +1,43 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClStayConstraint.h
+
+#ifndef ClStayConstraint_H
+#define ClStayConstraint_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+#include "ClEditOrStayConstraint.h"
+
+class ClStayConstraint : public ClEditOrStayConstraint {
+ typedef ClEditOrStayConstraint super;
+ public:
+
+ ClStayConstraint(const ClVariable var,
+ const ClStrength &strength = ClsWeak(), double weight = 1.0 ) :
+ ClEditOrStayConstraint(var,strength,weight)
+ { }
+
+ virtual bool isStayConstraint() const
+ { return true; }
+
+#ifndef CL_NO_IO
+ virtual ostream &PrintOn(ostream &xo) const
+ { super::PrintOn(xo); return xo << " STAY)"; }
+#endif
+
+ private:
+};
+
+#endif
diff --git a/libs/cassowary/cassowary/ClStrength.h b/libs/cassowary/cassowary/ClStrength.h
new file mode 100644
index 0000000000..644c04cb5f
--- /dev/null
+++ b/libs/cassowary/cassowary/ClStrength.h
@@ -0,0 +1,91 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClStrength.h
+
+#ifndef ClStrength_H
+#define ClStrength_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include <string>
+
+#include "Cassowary.h"
+#include "ClSymbolicWeight.h"
+
+using std::string;
+
+class ClStrength;
+
+const ClStrength &ClsRequired();
+const ClStrength &ClsStrong();
+const ClStrength &ClsMedium();
+const ClStrength &ClsWeak();
+
+class ClStrength {
+ public:
+
+ ClStrength(const string &Name, const ClSymbolicWeight &symbolicWeight) :
+ _name(Name), _symbolicWeight(symbolicWeight)
+ { }
+
+ // special case for when nLevels = 3, should assert nLevels() == 3
+ ClStrength(const string &Name, double w1, double w2, double w3);
+
+ virtual ~ClStrength()
+ { }
+
+ virtual bool IsRequired() const
+ { return (_symbolicWeight == ClsRequired()._symbolicWeight); }
+
+#ifndef CL_NO_IO
+ virtual ostream &PrintOn(ostream &xo) const
+ {
+ xo << Name();
+ if (!IsRequired())
+ xo << ":" << symbolicWeight();
+ return xo;
+ }
+
+ friend ostream& operator<<(ostream &xos, const ClStrength &Cls)
+ { Cls.PrintOn(xos); return xos; }
+
+#endif
+
+ virtual const ClSymbolicWeight &symbolicWeight() const
+ { return _symbolicWeight; }
+
+ void SetPv(void *pv)
+ { _pv = pv; }
+
+ void *Pv() const
+ { return _pv; }
+
+ private:
+ string Name() const
+ { return _name; }
+
+ void SetName(string Name)
+ { _name = Name; }
+
+ void SetSymbolicWeight(const ClSymbolicWeight &symbolicWeight)
+ { _symbolicWeight = symbolicWeight; }
+
+ // instance variables
+ string _name;
+ ClSymbolicWeight _symbolicWeight;
+
+ void *_pv;
+
+};
+
+#endif
diff --git a/libs/cassowary/cassowary/ClSymbolicWeight.h b/libs/cassowary/cassowary/ClSymbolicWeight.h
new file mode 100644
index 0000000000..1c0339c887
--- /dev/null
+++ b/libs/cassowary/cassowary/ClSymbolicWeight.h
@@ -0,0 +1,197 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClSymbolicWeight.h
+
+#ifndef ClSymbolicWeight_H
+#define ClSymbolicWeight_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+#include "ClErrors.h"
+#include <vector>
+#include <iostream>
+
+using std::vector;
+using std::ostream;
+
+class ClSymbolicWeight {
+ public:
+ ClSymbolicWeight(unsigned int CLevels = 3, Number value = 0.0);
+
+ ClSymbolicWeight(Number w1, Number w2, Number w3);
+
+ ClSymbolicWeight(const vector<Number> &weights);
+
+ static ClSymbolicWeight &Zero();
+
+ ClSymbolicWeight &negated();
+
+ ClSymbolicWeight &MultiplyMe(Number n);
+
+ ClSymbolicWeight Times(Number n) const
+ { ClSymbolicWeight cl = *this; cl.MultiplyMe(n); return cl; }
+
+ ClSymbolicWeight DivideBy(Number n) const;
+
+ ClSymbolicWeight &addtoMe(const ClSymbolicWeight &cl);
+
+ ClSymbolicWeight Add(const ClSymbolicWeight &cl) const
+ { ClSymbolicWeight clRet = *this; clRet.addtoMe(cl); return clRet; }
+
+ ClSymbolicWeight Subtract(const ClSymbolicWeight &cl) const;
+
+ ClSymbolicWeight operator*(const Number &n) const
+ { return Times(n); }
+
+ ClSymbolicWeight operator/(const Number &n) const
+ { return DivideBy(n); }
+
+ // FIXGJB: can we express this statically?
+ ClSymbolicWeight operator*(ClSymbolicWeight &w) const
+ { throw ExCLInternalError("Multiplication of symbolic weights encountered");
+ return w; }
+ ClSymbolicWeight &operator*=(ClSymbolicWeight &w)
+ { throw ExCLInternalError("Multiplicative assignment of symbolic weights encountered");
+ return w; }
+
+ // FIXGJB: can we express this statically?
+ ClSymbolicWeight operator-() const
+ { throw ExCLInternalError("Can not negate a symbolic weight");
+ return ClSymbolicWeight::Zero(); }
+
+ friend ClSymbolicWeight ReciprocalOf(const ClSymbolicWeight &);
+
+ ClSymbolicWeight &operator*=(const Number &n)
+ { return MultiplyMe(n); }
+
+ ClSymbolicWeight operator+(const ClSymbolicWeight &cl) const
+ { return Add(cl); }
+
+ ClSymbolicWeight operator+=(const ClSymbolicWeight &cl)
+ { return addtoMe(cl); }
+
+ ClSymbolicWeight operator*(const Number &n)
+ { ClSymbolicWeight answer(*this);
+ answer *= n;
+ return answer; }
+
+ bool lessThan(const ClSymbolicWeight &cl) const;
+ bool lessThanOrEqual(const ClSymbolicWeight &cl) const;
+ bool equal(const ClSymbolicWeight &cl) const;
+ bool greaterThan(const ClSymbolicWeight &cl) const;
+ bool greaterThanOrEqual(const ClSymbolicWeight &cl) const;
+ bool isNegative() const;
+
+ friend bool operator==(const ClSymbolicWeight &cl1, const ClSymbolicWeight &cl2)
+ { return cl1.equal(cl2); }
+
+ friend bool operator!=(const ClSymbolicWeight &cl1, const ClSymbolicWeight &cl2)
+ { return !(cl1 == cl2); }
+
+ friend bool operator<(const ClSymbolicWeight &cl1, const ClSymbolicWeight &cl2)
+ { return cl1.lessThan(cl2); }
+
+ friend bool operator>(const ClSymbolicWeight &cl1, const ClSymbolicWeight &cl2)
+ { return (cl2 < cl1); }
+
+ // function.h provides operator>, >=, <= from operator<
+
+ double AsDouble() const
+ {
+ vector<Number>::const_reverse_iterator i = _values.rbegin();
+ Number sum = 0;
+ Number factor = 1;
+ // A. Beurive' Wed Jul 7 11:07:47 CEST 1999
+ Number multiplier = 1000000;
+ for ( ; i != _values.rend(); ++i)
+ {
+ sum += *i * factor;
+ factor *= multiplier;
+ }
+ return sum;
+ }
+
+#ifndef CL_NO_IO
+ ostream &PrintOn(ostream &xo) const
+ {
+ vector<Number>::const_iterator i = _values.begin();
+ if (i == _values.end())
+ return xo;
+
+ xo << *i;
+ for (++i; i != _values.end(); ++i)
+ {
+ xo << "," << *i;
+ }
+ return xo;
+ }
+
+ // FIXGJB: use a template function to generate these automatically
+ friend ostream& operator<<(ostream &xos, const ClSymbolicWeight &clsw)
+ { clsw.PrintOn(xos); return xos; }
+#endif
+
+ int CLevels() const
+ { return _values.size(); }
+
+ friend bool ClApprox(const ClSymbolicWeight &cl, Number n);
+ friend bool ClApprox(const ClSymbolicWeight &cl1, const ClSymbolicWeight &cl2);
+
+ private:
+ vector<Number> _values;
+
+ void push_back(Number d)
+ { _values.push_back(d); }
+
+};
+
+inline bool ClApprox(const ClSymbolicWeight &cl, Number n)
+{
+ vector<Number>::const_iterator it = cl._values.begin();
+ if (!ClApprox(*it,n))
+ return false;
+
+ ++it;
+ for (; it != cl._values.end(); ++it)
+ {
+ if (!ClApprox(*it,0))
+ return false;
+ }
+
+ return true;
+}
+
+inline bool ClApprox(const ClSymbolicWeight &cl1, const ClSymbolicWeight &cl2)
+{
+ vector<Number>::const_iterator it1 = cl1._values.begin();
+ vector<Number>::const_iterator it2 = cl2._values.begin();
+
+ for (; it1 != cl1._values.end() && it2 != cl2._values.end();
+ ++it1, ++it2)
+ {
+ if (!ClApprox(*it1,*it2))
+ return false;
+ }
+
+ if (it1 == cl1._values.end() && it2 == cl2._values.end())
+ return true;
+
+ return false;
+}
+
+inline ClSymbolicWeight ReciprocalOf(const ClSymbolicWeight &)
+{ throw(ExCLInternalError("Cannot take ReciprocalOf symbolic weight"));
+ return ClSymbolicWeight::Zero(); }
+
+#endif
diff --git a/libs/cassowary/cassowary/ClTableau.h b/libs/cassowary/cassowary/ClTableau.h
new file mode 100644
index 0000000000..117ed0fb9d
--- /dev/null
+++ b/libs/cassowary/cassowary/ClTableau.h
@@ -0,0 +1,230 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClTableau.h
+
+#ifndef ClTableau_H
+#define ClTableau_H
+
+#include <iostream>
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+#include "ClLinearExpression.h"
+#include "ClVariable.h"
+#include "ClTypedefs.h"
+
+
+#ifndef CL_NO_IO
+class ClTableau;
+
+ostream &operator<<(ostream &xo, const ClTableau &clt);
+
+ostream &operator<<(ostream &xo, const ClVarSet &varset);
+
+ostream &operator<<(ostream &xo, const ClTableauColumnsMap &varmap);
+
+ostream &operator<<(ostream &xo, const ClTableauRowsMap &rows);
+
+ostream &operator<<(ostream &xo, const ClVarVector &varlist);
+#endif // CL_NO_IO
+
+class ClTableau {
+
+ public:
+ // No public constructor, since this does nothing but support
+ // an ADT for the ClSimplexSolver
+
+ // Variable v has been removed from an Expression. If the
+ // Expression is in a tableau the corresponding basic variable is
+ // subject (or if subject is nil then it's in the objective function).
+ // Update the column cross-indices.
+ void NoteRemovedVariable(ClVariable v, ClVariable subject)
+ {
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ std::cerr << "(" << v << ", " << subject << ")" << std::endl;
+#endif
+ ClVarSet &column = _columns[v];
+ ClVarSet::const_iterator it = column.find(subject);
+ assert(it != column.end());
+ column.erase(it);
+#ifdef CL_TRACE_VERBOSE
+ std::cerr << "v = " << v << " and Columns[v].size() = "
+ << column.size() << std::endl;
+#endif
+ if (column.size() == 0)
+ {
+ _columns.erase(v);
+ _externalRows.erase(v);
+ _externalParametricVars.erase(v);
+ }
+ }
+
+ // v has been added to the linear Expression for subject
+ // update column cross indices
+ void NoteAddedVariable(ClVariable v, ClVariable subject)
+ {
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ std::cerr << "(" << v << ", " << subject << ")" << std::endl;
+#endif
+ _columns[v].insert(subject);
+ if (v.IsExternal() && !FIsBasicVar(v))
+ {
+ _externalParametricVars.insert(v);
+ }
+ }
+
+#ifndef CL_NO_IO
+ std::ostream &PrintOn(ostream &xo) const;
+
+ ostream &PrintInternalInfo(ostream &xo) const;
+
+ ostream &printExternalVariablesTo(ostream &xo) const;
+
+#endif
+
+ // Check integrity of the tableau
+ // not complete, yet, but a start, at least
+ // Guard calls to AssertValid with CL_SOLVER_CHECK_INTEGRITY,
+ // since this is expensive
+ virtual void AssertValid() const {
+#ifndef NDEBUG
+ // all external basic variables are in _externalRows
+ // and all external parametric variables are in _externalParametricVars
+ ClTableauRowsMap::const_iterator itRow = _rows.begin();
+ for (; itRow != _rows.end(); ++itRow)
+ {
+ const ClVariable clv = (*itRow).first;
+ if (clv.IsExternal())
+ {
+ if (_externalRows.find(clv) == _externalRows.end())
+ {
+#ifndef CL_NO_IO
+ std::cerr << "External basic variable " << clv
+ << " is not in _externalRows" << std::endl;
+#endif
+ }
+ }
+ const ClLinearExpression *pcle = RowExpression(clv);
+ assert(pcle);
+ ClVarToNumberMap::const_iterator it = pcle->Terms().begin();
+ for (; it != pcle->Terms().end(); ++it)
+ {
+ ClVariable clv = (*it).first;
+ if (clv.IsExternal())
+ {
+ if (_externalParametricVars.find(clv) == _externalParametricVars.end())
+ {
+#ifndef CL_NO_IO
+ std::cerr << "External parametric variable " << clv
+ << " is not in _externalParametricVars" << std::endl;
+#endif
+ }
+ }
+ }
+ }
+#endif /* !NDEBUG */
+ }
+
+
+ protected:
+ // Constructor -- want to start with empty objects so not much to do
+ ClTableau()
+ { }
+
+ virtual ~ClTableau();
+
+ // Add v=expr to the tableau, update column cross indices
+ // v becomes a basic variable
+ // expr is now owned by ClTableau class,
+ // and ClTableauis responsible for deleting it
+ // (also, expr better be allocated on the heap!)
+ void addRow(ClVariable v, const ClLinearExpression &expr);
+
+ // Remove v from the tableau -- remove the column cross indices for v
+ // and remove v from every Expression in rows in which v occurs
+ // returns a pointer to the variable (since we often want to delete
+ // the variable)
+ ClVariable RemoveColumn(ClVariable v);
+
+ // Remove the basic variable v from the tableau row v=expr
+ // Then update column cross indices
+ // Probably want to call delete on the ClLinearExpression * returned
+ // unless you're adding that same Expression back into the
+ // tableau
+ ClLinearExpression *RemoveRow(ClVariable v);
+
+ // Replace all occurrences of oldVar with expr, and update column cross indices
+ // oldVar should now be a basic variable
+ void SubstituteOut(ClVariable oldVar, const ClLinearExpression &expr);
+
+ ClTableauColumnsMap Columns()
+ { return _columns; }
+
+ ClTableauRowsMap Rows()
+ { return _rows; }
+
+ // return true iff the variable subject is in the Columns keys
+ bool ColumnsHasKey(ClVariable subject) const
+ {
+ ClTableauColumnsMap::const_iterator i = _columns.find(subject);
+ return (i != _columns.end());
+ }
+
+ const ClLinearExpression *RowExpression(ClVariable v) const
+ {
+ ClTableauRowsMap::const_iterator i = _rows.find(v);
+ if (i != _rows.end())
+ return (*i).second;
+ else
+ return 0;
+ }
+
+ ClLinearExpression *RowExpression(ClVariable v)
+ {
+ const ClTableau *pthis = const_cast<const ClTableau *>(this);
+ return const_cast<ClLinearExpression *>(pthis->RowExpression(v));
+ }
+
+
+ bool FIsBasicVar(ClVariable v)
+ { return RowExpression(v) != 0; }
+
+ // private: FIXGJB: can I improve the encapsulation?
+
+ // _columns is a mapping from variables which occur in expressions to the
+ // set of basic variables whose expressions contain them
+ // i.e., it's a mapping from variables in expressions (a column) to the
+ // set of rows that contain them
+ ClTableauColumnsMap _columns;
+
+ // _rows maps basic variables to the expressions for that row in the tableau
+ ClTableauRowsMap _rows;
+
+ // the collection of basic variables that have infeasible rows
+ // (used when reoptimizing)
+ ClVarSet _infeasibleRows;
+
+ // the set of rows where the basic variable is external
+ // this was added to the C++ version to reduce time in SetExternalVariables()
+ ClVarSet _externalRows;
+
+ // the set of external variables which are parametric
+ // this was added to the C++ version to reduce time in SetExternalVariables()
+ ClVarSet _externalParametricVars;
+
+};
+
+#endif
diff --git a/libs/cassowary/cassowary/ClTypedefs.h b/libs/cassowary/cassowary/ClTypedefs.h
new file mode 100644
index 0000000000..74b625a72b
--- /dev/null
+++ b/libs/cassowary/cassowary/ClTypedefs.h
@@ -0,0 +1,48 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClTypedefs.h
+
+#ifndef CL_TYPEDEFS_H__
+#define CL_TYPEDEFS_H__
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "ClLinearExpression_fwd.h"
+#include <set>
+#include <map>
+#include <vector>
+
+using std::set;
+using std::map;
+using std::vector;
+
+class ClVariable;
+class ClConstraint;
+class ClEditInfo;
+
+typedef set<ClVariable> ClVarSet;
+typedef map<ClVariable, ClVarSet > ClTableauColumnsMap;
+typedef map<ClVariable, ClLinearExpression *> ClTableauRowsMap;
+
+// For Solver
+typedef map<const ClConstraint *, ClVarSet> ClConstraintToVarSetMap;
+typedef map<const ClConstraint *, ClVariable> ClConstraintToVarMap;
+typedef map<ClVariable, const ClConstraint *> ClVarToConstraintMap;
+typedef vector<ClVariable> ClVarVector;
+
+typedef set<const ClConstraint *> ClConstraintSet;
+
+// For FDSolver
+typedef map<ClVariable, ClConstraintSet> ClVarToConstraintSetMap;
+
+#endif
diff --git a/libs/cassowary/cassowary/ClVariable.h b/libs/cassowary/cassowary/ClVariable.h
new file mode 100644
index 0000000000..03814e5ef2
--- /dev/null
+++ b/libs/cassowary/cassowary/ClVariable.h
@@ -0,0 +1,166 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClVariable.h
+// A handle on ClAbstractVariable-s
+
+#ifndef ClVariable_H
+#define ClVariable_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include <cstdio>
+#include <map>
+#include <string>
+#include "Cassowary.h"
+#include "ClFloatVariable.h"
+#include "ClFDVariable.h"
+
+using std::map;
+using std::string;
+
+class ClVariable;
+typedef map<const string,ClVariable> StringToVarMap;
+
+
+class ClVariable {
+ ClAbstractVariable *pclv;
+public:
+ // converters from raw ClAbstractVariable
+ ClVariable(ClAbstractVariable *pclv_) : pclv(pclv_) { }
+ ClVariable(ClAbstractVariable &clv_) : pclv(&clv_) { }
+
+ // Copy ctr
+ ClVariable(const ClVariable &clv_) : pclv(clv_.pclv) { }
+
+ /// These ctrs build ClFloatVariable-s
+ ClVariable(string name, Number Value = 0.0)
+ : pclv(new ClFloatVariable(name,Value))
+ { if (pmapStrPclv) { (*pmapStrPclv)[name] = *this; } }
+ ClVariable(Number Value = 0.0)
+ : pclv(new ClFloatVariable(Value)) { }
+ ClVariable(long number, char *prefix, Number Value = 0.0)
+ : pclv(new ClFloatVariable(number,prefix,Value)) { }
+
+ // This one builds a ClFDVariable
+ ClVariable(ClFDVariable *pcfv)
+ : pclv(pcfv)
+ { if (pmapStrPclv) { (*pmapStrPclv)[pcfv->Name()] = *this; } }
+
+ /// permit ClVariables to be used as pointers to pclvs
+ ClAbstractVariable *operator->() { return pclv; }
+ const ClAbstractVariable *operator->() const { return pclv; }
+
+ /// and also forward the function calls along
+
+
+ bool IsFloatVariable() const { assert(pclv); return pclv->IsFloatVariable(); }
+ bool IsFDVariable() const { assert(pclv); return pclv->IsFDVariable(); }
+ bool IsDummy() const { assert(pclv); return pclv->IsDummy(); }
+ bool IsExternal() const { assert(pclv); return pclv->IsExternal(); }
+ bool IsPivotable() const { assert(pclv); return pclv->IsPivotable(); }
+ bool IsRestricted() const { assert(pclv); return pclv->IsRestricted(); }
+
+ string Name() const { assert(pclv); return pclv->Name(); }
+
+ Number Value() const { assert(pclv); return pclv->Value(); }
+ int IntValue() const { assert(pclv); return pclv->IntValue(); }
+ void SetValue(Number Value)
+ { assert(pclv); pclv->SetValue(Value); }
+ void ChangeValue(Number Value)
+ { assert(pclv); pclv->ChangeValue(Value); }
+ void SetPv(void *pv)
+ { assert(pclv); pclv->SetPv(pv); }
+ void *Pv() const
+ { assert(pclv); return pclv->Pv(); }
+
+ void SetName(string const &nm) {
+ assert(pclv);
+ if (pmapStrPclv) {
+ pmapStrPclv->erase(Name());
+ (*pmapStrPclv)[nm] = *this;
+ }
+ pclv->SetName(nm);
+ }
+
+ ClAbstractVariable *get_pclv() const { return pclv; }
+ bool IsNil() const { return pclv == 0; }
+
+ virtual FDNumber DesiredValue() const
+ { assert(false); }
+
+ virtual list<FDNumber> *PlfdnDomain()
+ { assert(false); return 0; }
+
+ static void SetVarMap(StringToVarMap *pmap) { pmapStrPclv = pmap; }
+ static StringToVarMap *VarMap() { return pmapStrPclv; }
+ static StringToVarMap *pmapStrPclv;
+#ifndef CL_NO_IO
+ ostream &PrintOn(ostream &xo) const
+ {
+ if (pclv) return pclv->PrintOn(xo); /* return xo << "@" << pclv << endl; */
+ return xo << "clvNil";
+ }
+#endif
+
+ friend bool operator<(ClVariable cl1, ClVariable cl2)
+ { return cl1.pclv < cl2.pclv; }
+
+ friend bool operator==(ClVariable cl1, ClVariable cl2)
+ { return cl1.pclv == cl2.pclv; }
+
+ friend bool operator!=(ClVariable cl1, ClVariable cl2)
+ { return !(cl1 == cl2); }
+
+};
+
+#ifndef CL_NO_IO
+inline ostream &operator<<(ostream &xo, const ClVariable &clv)
+{ return clv.PrintOn(xo); }
+#endif
+
+#ifdef CL_USE_HASH_MAP_AND_SET
+struct hash<ClVariable> {
+ size_t operator()(const ClVariable & v) const
+ { return size_t((unsigned long)v.get_pclv()/CL_PTR_HASH_DIVISOR); }
+};
+#endif
+
+
+#include <math.h>
+
+// Compare two double-s approximately, since equality is no good
+inline bool ClApprox(double a, double b)
+{
+ const double epsilon = 1.0e-8;
+ if (a > b) {
+ return (a - b) < epsilon;
+ } else {
+ return (b - a) < epsilon;
+ }
+}
+
+// Can remove these if I decide to
+// autoconvert from ClVariable-s to double-s
+inline bool ClApprox(ClVariable clv, double b)
+{
+ return ClApprox(clv->Value(),b);
+}
+
+inline bool ClApprox(double a, ClVariable clv)
+{
+ return ClApprox(a,clv->Value());
+}
+
+extern ClVariable clvNil;
+
+#endif
diff --git a/libs/cassowary/cassowary/Makefile.am b/libs/cassowary/cassowary/Makefile.am
new file mode 100644
index 0000000000..cc581b80ff
--- /dev/null
+++ b/libs/cassowary/cassowary/Makefile.am
@@ -0,0 +1,36 @@
+MAINTAINERCLEANFILES = autom4te.cache Makefile.in
+
+noinst_HEADERS = \
+ Cassowary.h \
+ ClAbstractVariable.h \
+ ClDummyVariable.h \
+ ClObjectiveVariable.h \
+ ClSlackVariable.h \
+ ClConstraint.h \
+ ClConstraintHash.h \
+ ClEditConstraint.h \
+ ClEditOrStayConstraint.h \
+ ClErrors.h \
+ ClLinearConstraint.h \
+ ClLinearEquation.h \
+ ClLinearExpression.h \
+ ClLinearExpression_fwd.h \
+ ClLinearInequality.h \
+ ClSolver.h \
+ ClSimplexSolver.h \
+ ClStayConstraint.h \
+ ClStrength.h \
+ ClSymbolicWeight.h \
+ ClTableau.h \
+ ClFDVariable.h \
+ ClFDConnectorVariable.h \
+ ClFloatVariable.h \
+ ClVariable.h \
+ ClReader.h \
+ ClTypedefs.h \
+ ClPoint.h \
+ cl_auto_ptr.h \
+ config-inline.h \
+ debug.h \
+ timer.h
+
diff --git a/libs/cassowary/cassowary/cl_auto_ptr.h b/libs/cassowary/cassowary/cl_auto_ptr.h
new file mode 100644
index 0000000000..3c37429676
--- /dev/null
+++ b/libs/cassowary/cassowary/cl_auto_ptr.h
@@ -0,0 +1,69 @@
+// $Id$
+// See http://cseng.aw.com/bookdetail.qry?ISBN=0-201-63371-X&ptype=634
+// auto_ptr from More Effective C++ an earlier appendix (works w/ egcs)
+
+
+#ifndef CL_AUTO_PTR_H
+#define CL_AUTO_PTR_H
+
+#ifdef _MSC_VER
+#include <memory>
+template<class T>
+void ReinitializeAutoPtr(auto_ptr<T> &apref, T *pt)
+{
+ auto_ptr<T> ap(pt);
+ apref = ap;
+}
+#define cl_auto_ptr auto_ptr
+#else
+// FIXGJB: This implementation for egcs is buggy -- be careful
+// and replace ASAP
+template<class T>
+class cl_auto_ptr {
+ public:
+ explicit cl_auto_ptr(T *p = 0): pointee(p) {}
+
+ template<class U>
+ cl_auto_ptr(cl_auto_ptr<U>& rhs): pointee(rhs.release()) {}
+
+ ~cl_auto_ptr() { delete pointee; }
+
+ template<class U>
+ cl_auto_ptr<T>& operator=(cl_auto_ptr<U>& rhs)
+ {
+ if (this != &rhs) reset(rhs.release());
+ return *this;
+ }
+
+ T& operator*() const { return *pointee; }
+
+ T* operator->() const { return pointee; }
+
+ T* get() const { return pointee; }
+
+ T* release()
+ {
+ T *oldPointee = pointee;
+ pointee = 0;
+ return oldPointee;
+ }
+
+ // protected:
+ // This is non-standard
+ void reset(T *p = 0) { delete pointee; pointee = p; }
+
+ private:
+ T *pointee;
+};
+
+template<class T>
+void ReinitializeAutoPtr(cl_auto_ptr<T> &apref, T *pt)
+{
+ apref.reset(pt);
+}
+
+
+#endif
+
+
+#endif
diff --git a/libs/cassowary/cassowary/config-inline.h b/libs/cassowary/cassowary/config-inline.h
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/libs/cassowary/cassowary/config-inline.h
@@ -0,0 +1 @@
+
diff --git a/libs/cassowary/cassowary/debug.h b/libs/cassowary/cassowary/debug.h
new file mode 100644
index 0000000000..aa0499c641
--- /dev/null
+++ b/libs/cassowary/cassowary/debug.h
@@ -0,0 +1,48 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// debug.h
+
+#ifndef CASSOWARY_DEBUG_H_
+#define CASSOWARY_DEBUG_H_
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include <vector>
+#include "Cassowary.h"
+
+#ifdef CL_TRACE
+class Tracer {
+ public:
+ Tracer(const char *const sz) : sz_(sz) { cerr << "* " << sz; }
+ ~Tracer() { cerr << "x " << sz_ << " exited." << endl; }
+ private:
+ const char *const sz_;
+};
+
+inline void CtrTracer(const char *const sz, const void *pv)
+{ cerr << "@+ " << sz << " ctrnew@ " << pv << endl; }
+
+inline void DtrTracer(const char *const sz, const void *pv)
+{ cerr << "@- " << sz << " dtrnew@ " << pv << endl; }
+
+#else
+class Tracer {
+ public:
+ Tracer(const char *const) { }
+};
+
+inline void CtrTracer(const char *const, const void *) { }
+inline void DtrTracer(const char *const, const void *) { }
+#endif // CL_TRACE
+
+#endif
diff --git a/libs/cassowary/cassowary/timer.h b/libs/cassowary/cassowary/timer.h
new file mode 100644
index 0000000000..6bad1a6fef
--- /dev/null
+++ b/libs/cassowary/cassowary/timer.h
@@ -0,0 +1,176 @@
+/* $Id$ */
+#ifndef _TIMER_H_
+#define _TIMER_H_
+
+// Programmer: John P. Russo
+// --------------------------
+// John Russo has given permission to any of my students to use his
+// "timer" class.
+//
+// Please give full credit to him any time you wish to use this class.
+// Hossein Hakimzadeh 11/5/96
+
+/************************** timer.cpp **********************************
+
+ A simple example that shows how C++ classes can be used to implement
+ a "Timer" object, which mimics the familiar actions of a stopwatch.
+
+ The code relies heavily on the clock() function defined in the time
+ library. The clock() function returns the number of "ticks" that have
+ elapsed since a program starts. The size of a "tick" is compiler
+ dependent, but for PC compilers is about 1/18 second.
+
+ The problem with the clock function is that it is not convenient to
+ use for typical timing operations. The timer class, defined below, by
+ contrast, shows that an object-oriented approach to modules can
+ provide tools that are natural and easy to use.
+
+= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+#include <time.h>
+
+class Timer
+{
+ //==================== public section ================================
+
+ // The functions and/or data in the public section of a class are
+ // accessible to anyone who uses the Timer class.
+
+public:
+ Timer(); // Constructor, used to declare Timer objects
+ void Start(); // Starts a timer object
+ void Stop(); // Stop a timer object
+ void Reset(); // Reset timer object
+ int IsRunning(); // Is the timer object running?
+ double ElapsedTime(); // How much time has been recorded?
+ double Resolution(); // Shortest measurable amount of time
+
+ //-------------------- private section -------------------------------
+
+ // The functions and/or data in the private section of a class are NOT
+ // accessible to those who use the Timer class. They are accessible by
+ // member functions of the class. This allows access to the data to be
+ // carefully controlled.
+
+private:
+ long StartReading; // Number of ticks when timer object last started.
+ long ElapsedTicks; // Number of ticks on timer object.
+ int TimerIsRunning; // 1 if and only if timer object is running.
+ double TicksPerSecond() // This inline function is used to convert
+// {return 18.206481;} // "ticks" (returned by clock() ) to seconds.
+ {return CLOCKS_PER_SEC;} // "ticks" (returned by clock() ) to seconds.
+ // In most UNIX systems this is 1000000
+};
+
+/**************************** Start ************************************
+
+ If the declaration "Timer StopWatch;" has been made, the the call,
+ "StopWatch.Start();" is like push the start button of a real stopwatch.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+void Timer::Start()
+{
+ TimerIsRunning = 1; // Stopwatch is now running
+ StartReading = clock(); // Look at internal clock and remember reading
+}
+
+/**************************** Stop ************************************
+
+ Looks at the PC's internal clock and computes the number of ticks that
+ have elapsed since the timer was started.
+
+ Note that if a timer is not reset, it can be used to time several events
+ and return the elapsed time for the enter set of events.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+void Timer::Stop()
+{
+ TimerIsRunning = 0; // Stop timer object.
+ ElapsedTicks += clock() - StartReading; // Add elapsed time to the
+} // previous time.
+
+/**************************** Reset ************************************
+
+ Clears a Timer of previous elapsed times, so that a new event can be
+ timed.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+void Timer::Reset()
+{
+ TimerIsRunning = 0; // Start not yet called.
+ ElapsedTicks = 0; // No time on timer object yet.
+}
+
+/************************** IsRunning ************************************
+
+ The data member, "TimerIsRunning" is used to keep track of whether a
+ timer is active, i.e. whether an event is being timed. While we want
+ those using the timer class to know when a timer is active, we do NOT
+ want them to directly access the TimerIsRunning variable. We solve this
+ problem, by making TimerIsRunning private and providing the public
+ "access function" below.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+int Timer::IsRunning()
+{
+ return TimerIsRunning;
+}
+
+/************************* ElapsedTime ***********************************
+
+ This function allows a client to determine the amount of time that has
+ elapsed on a timer object. Note that there are two possibilities:
+
+ 1) A timer object has been started and stopped. We can detect this
+ case, because the variable "TimerIsRunning" is false.
+
+ 2) A timer object is "running", i.e. is still in the process of timing
+ an event. It is not expected that this case will occur as frequently
+ as case 1).
+
+ In either case, this function converts ticks to seconds. Note that
+ since the function TicksPerSecond() returns a value of type double,
+ an implicit type conversion takes place before doing the division
+ required in either case.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+double Timer::ElapsedTime()
+{
+ if ( !TimerIsRunning ) // Normal case
+ return ElapsedTicks/TicksPerSecond();
+
+ else
+ return (ElapsedTicks + clock() - StartReading)/TicksPerSecond();
+}
+
+/************************** Resolution ***********************************
+
+ Althould we have no way of knowing how accurate the internal clock is,
+ we can predict its resolution, which is the shortest event that can be
+ measured by the clock.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+double Timer::Resolution()
+{
+ return 1/TicksPerSecond(); // Note 1 is coverted to 1.0 before division
+}
+
+/******************** Timer (constructor) *******************************
+
+ A "constructor" is a special class member function, one which has the
+ same name as the class. The "default constructor" is a constructor that
+ has no parameters. A constructor is called automatically when an
+ instance of a class is declared. For example, the constructor defined
+ below is called when the declaration "Timer T;" is executed.
+
+ If the programmer does not write a default constructor, then the
+ compiler will generate one automatically. However, by writing the
+ constructor below, we provide automatic initialization of timer objects.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+Timer::Timer()
+{
+ TimerIsRunning = 0; // Start not yet called.
+ ElapsedTicks = 0; // No time on timer object yet.
+}
+
+#endif /* _TIMER_H_ */
diff --git a/libs/cassowary/configure.ac b/libs/cassowary/configure.ac
new file mode 100644
index 0000000000..3e565d7709
--- /dev/null
+++ b/libs/cassowary/configure.ac
@@ -0,0 +1,64 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(cassowary)
+
+AC_CONFIG_AUX_DIR(.)
+AC_CANONICAL_HOST
+AC_CANONICAL_TARGET
+AC_VALIDATE_CACHED_SYSTEM_TUPLE()
+
+LIBCASSOWARY_MAJOR_VERSION=0
+LIBCASSOWARY_MINOR_VERSION=60
+LIBCASSOWARY_MICRO_VERSION=3
+
+AC_SUBST(LIBCASSOWARY_MAJOR_VERSION)
+AC_SUBST(LIBCASSOWARY_MINOR_VERSION)
+AC_SUBST(LIBCASSOWARY_MICRO_VERSION)
+
+BETA=
+
+LIBCASSOWARY_VERSION=$LIBCASSOWARY_MAJOR_VERSION.$LIBCASSOWARY_MINOR_VERSION.${LIBCASSOWARY_MICRO_VERSION}${BETA}
+LIBCASSOWARY_RELEASE=$LIBCASSOWARY_MAJOR_VERSION-$LIBCASSOWARY_MINOR_VERSION-${LIBCASSOWARY_MICRO_VERSION}${BETA}
+
+AC_SUBST(LIBCASSOWARY_SO_VERSION)
+AC_SUBST(LIBCASSOWARY_VERSION)
+AC_SUBST(LIBCASSOWARY_RELEASE)
+
+AM_INIT_AUTOMAKE(libcassowary,${LIBCASSOWARY_VERSION})
+
+AM_CONFIG_HEADER(config.h)
+
+dnl Checks for programs.
+
+AC_PROG_CC
+AC_PROG_CXX
+if test "$ac_cv_prog_cxx" = "no" ; then
+ AC_MSG_ERROR([*** libcassowary is C++. You don't appear to have a C++ compiler])
+fi
+
+CXXFLAGS="-g -D_REENTRANT"
+OPT_CXXFLAGS="-D_REENTRANT -O6 -fomit-frame-pointer -ffast-math -fstrength-reduce -funroll-loops -fmove-all-movables"
+if test x"$GXX" = xyes ; then
+ CXXFLAGS="$CXXFLAGS -Wall"
+fi
+if test x"$GXX" = xyes ; then
+ OPT_CXXFLAGS="$OPT_CXXFLAGS -Wall"
+fi
+
+AC_ARG_ENABLE(optimize,
+ [ --enable-optimize ask the compiler for its best optimizations.],
+ [ if test "x$enable_optimize" != "xno" ; then CXXFLAGS="$OPT_CXXFLAGS" ; fi ])
+
+AC_OBJEXT
+AC_PROG_RANLIB
+AM_PROG_LEX
+AC_PROG_YACC
+
+AC_LANG_CPLUSPLUS
+
+CFLAGS="$CFLAGS $GLIB_CFLAGS"
+CXXFLAGS="$CXXFLAGS $GLIB_CFLAGS"
+LIBS="$LIBS $GLIB_LIBS $POSIX_RTSCHED_LIBS"
+
+AC_OUTPUT([Makefile
+ cassowary/Makefile
+])