Merged with trunk, and a few trivial GUI updates etc.

git-svn-id: svn://localhost/ardour2/branches/midi@664 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2006-07-05 19:47:25 +00:00
parent 5dc4abef79
commit 22c20ab6f2
200 changed files with 5920 additions and 12700 deletions

View file

@ -62,6 +62,13 @@ class LibraryInfo(Environment):
#doing LINKFLAGS breaks -framework
#doing LIBS break link order dependency
def ENV_update(self, src_ENV):
for k in src_ENV.keys():
if k in self['ENV'].keys() and k in [ 'PATH', 'LD_LIBRARY_PATH',
'LIB', 'INCLUDE' ]:
self['ENV'][k]=SCons.Util.AppendPath(self['ENV'][k], src_ENV[k])
else:
self['ENV'][k]=src_ENV[k]
env = LibraryInfo (options = opts,
CPPPATH = [ '.' ],
@ -72,6 +79,7 @@ env = LibraryInfo (options = opts,
DISTCHECKDIR = '#ardour-' + version + '/check'
)
env.ENV_update(os.environ)
#----------------------------------------------------------------------
# Builders
@ -141,31 +149,31 @@ env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emit
# internationalization
#
# po_helper
#
# this is not a builder. we can't list the .po files as a target,
# because then scons -c will remove them (even Precious doesn't alter
# this). this function is called whenever a .mo file is being
# built, and will conditionally update the .po file if necessary.
#
def po_helper(po,pot):
args = [ 'msgmerge',
'--update',
po,
pot,
]
print 'Updating ' + po
return os.spawnvp (os.P_WAIT, 'msgmerge', args)
# mo_builder: builder function for (binary) message catalogs (.mo)
# po_builder: builder function to copy po files to the parent directory while updating them
#
# first source: .po file
# second source: .pot file
#
def po_builder(target,source,env):
os.spawnvp (os.P_WAIT, 'cp', ['cp', str(source[0]), str(target[0])])
args = [ 'msgmerge',
'--update',
str(target[0]),
str(source[1])
]
print 'Updating ' + str(target[0])
return os.spawnvp (os.P_WAIT, 'msgmerge', args)
po_bld = Builder (action = po_builder)
env.Append(BUILDERS = {'PoBuild' : po_bld})
# mo_builder: builder function for (binary) message catalogs (.mo)
#
# first source: .po file
#
def mo_builder(target,source,env):
po_helper (source[0].get_path(), source[1].get_path())
args = [ 'msgfmt',
'-c',
'-o',
@ -209,13 +217,13 @@ def i18n (buildenv, sources, installenv):
p_oze = [ os.path.basename (po) for po in glob.glob ('po/*.po') ]
languages = [ po.replace ('.po', '') for po in p_oze ]
m_oze = [ po.replace (".po", ".mo") for po in p_oze ]
for mo in m_oze[:]:
po = 'po/' + mo.replace (".mo", ".po")
installenv.Alias ('install', buildenv.MoBuild (mo, [ po, potfile ]))
for po_file in p_oze:
buildenv.PoBuild(po_file, ['po/'+po_file, potfile])
mo_file = po_file.replace (".po", ".mo")
installenv.Alias ('install', buildenv.MoBuild (mo_file, po_file))
for lang in languages[:]:
for lang in languages:
modir = (os.path.join (install_prefix, 'share/locale/' + lang + '/LC_MESSAGES/'))
moname = domain + '.mo'
installenv.Alias('install', installenv.InstallAs (os.path.join (modir, moname), lang + '.mo'))
@ -420,9 +428,8 @@ libraries['ardour_cp'] = LibraryInfo (LIBS='ardour_cp', LIBPATH='#libs/surfaces/
libraries['ardour'] = LibraryInfo (LIBS='ardour', LIBPATH='#libs/ardour', CPPPATH='#libs/ardour')
libraries['midi++2'] = LibraryInfo (LIBS='midi++', LIBPATH='#libs/midi++2', CPPPATH='#libs/midi++2')
libraries['pbd3'] = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd3', CPPPATH='#libs/pbd3')
libraries['pbd'] = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd', CPPPATH='#libs/pbd')
libraries['gtkmm2ext'] = LibraryInfo (LIBS='gtkmm2ext', LIBPATH='#libs/gtkmm2ext', CPPPATH='#libs/gtkmm2ext')
#libraries['cassowary'] = LibraryInfo(LIBS='cassowary', LIBPATH='#libs/cassowary', CPPPATH='#libs/cassowary')
#
# Check for libusb
@ -546,7 +553,7 @@ if env['SYSLIBS']:
subdirs = [
'libs/libsndfile',
'libs/pbd3',
'libs/pbd',
'libs/midi++2',
'libs/ardour'
]
@ -599,10 +606,9 @@ else:
]
subdirs = [
# 'libs/cassowary',
'libs/sigc++2',
'libs/libsndfile',
'libs/pbd3',
'libs/pbd',
'libs/midi++2',
'libs/ardour'
]
@ -836,30 +842,48 @@ if env['LIBLO']:
env.Merge ([ libraries['core'] ])
#
# fix scons nitpickiness on APPLE
#
if env['DIST_TARGET'] == 'panther' or env['DIST_TARGET'] == 'tiger':
env.Append(CCFLAGS="-I/opt/local/include", LINKFLAGS="-L/opt/local/lib")
#
# i18n support
#
conf = Configure (env)
if env['NLS']:
nls_error = 'This system is not configured for internationalized applications. An english-only version will be built:'
print 'Checking for internationalization support ...'
have_gettext = conf.TryAction(Action('xgettext --version'))
if have_gettext[0] != 1:
print 'This system is not configured for internationalized applications (no xgettext command). An english-only version will be built\n'
nls_error += ' No xgettext command.'
env['NLS'] = 0
else:
print "Found xgettext"
have_msgmerge = conf.TryAction(Action('msgmerge --version'))
if have_msgmerge[0] != 1:
nls_error += ' No msgmerge command.'
env['NLS'] = 0
else:
print "Found msgmerge"
if not conf.CheckCHeader('libintl.h'):
nls_error += ' No libintl.h.'
env['NLS'] = 0
if conf.CheckCHeader('libintl.h') == None:
print 'This system is not configured for internationalized applications (no libintl.h). An english-only version will be built\n'
env['NLS'] = 0
if env['NLS'] == 0:
print nls_error
else:
print "International version will be built."
env = conf.Finish()
if env['NLS'] == 1:
env.Append(CCFLAGS="-DENABLE_NLS")
Export('env install_prefix final_prefix config_prefix final_config_prefix libraries i18n version subst_dict')
#

View file

@ -27,7 +27,7 @@ gtkardour.Merge ([
libraries['ardour_cp'],
libraries['gtkmm2ext'],
libraries['midi++2'],
libraries['pbd3'],
libraries['pbd'],
libraries['gtkmm2'],
libraries['glib2'],
libraries['libgnomecanvas2'],
@ -255,8 +255,7 @@ else:
env.Alias('install', env.InstallAs(os.path.join(install_prefix, 'bin')+'/ardour2', ardoursh))
if env['NLS']:
Export('gtkardour', 'intl_files')
SConscript ('po/SConscript')
i18n (gtkardour, gtkardour_files+skipped_files+fft_analysis_files, env)
# configuration files
env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour2_ui.rc'))

View file

@ -5,6 +5,9 @@ cFrameBase 0.75 0.75 0.76 1.0
cAudioTrackBase 0.75 0.75 0.85 0.41
cAudioTrackOutline 0.00 0.00 0.00 1.00
cAudioBusBase 0.75 0.80 0.75 0.41
cMidiTrackBase 0.85 0.75 0.75 0.41
cMidiTrackOutline 0.00 0.00 0.00 1.00
cMidiBusBase 0.80 0.75 0.75 0.41
cMeterBar 0.40 0.40 0.40 1.0
cTempoBar 0.45 0.45 0.45 1.0
cMarkerBar 0.50 0.50 0.50 1.0

View file

@ -520,6 +520,25 @@ style "audio_bus_base"
bg[NORMAL] = {0, 0.36, 0.40 }
}
style "midi_track_base" = "default_base"
{
font_name = "sans 6"
fg[NORMAL] = { 0.77, 0.77, 0.72 }
bg[NORMAL] = { 0.22, 0.18, 0.18 }
bg[ACTIVE] = { 0.20, 0.20, 0.20 }
bg[PRELIGHT] = { 0.20, 0.20, 0.20 }
bg[INSENSITIVE] = { 0.20, 0.20, 0.20 }
bg[SELECTED] = { 0.20, 0.20, 0.20 }
}
style "midi_bus_base"
{
font_name = "sans 6"
fg[NORMAL] = { 0.77, 0.77, 0.72 }
fg[NORMAL] = { 0.8, 0.7, 0.2 }
bg[NORMAL] = {0.40, 0.36, 0.00 }
}
style "track_name_display"
{
font_name = "sans medium 8"

View file

@ -544,7 +544,7 @@ ARDOUR_UI::update_buffer_load ()
}
void
ARDOUR_UI::count_recenabled_diskstreams (AudioDiskstream& ds)
ARDOUR_UI::count_recenabled_diskstreams (Diskstream& ds)
{
if (ds.record_enabled()) {
rec_enabled_diskstreams++;
@ -572,7 +572,7 @@ ARDOUR_UI::update_disk_space()
if (session->actively_recording()){
rec_enabled_diskstreams = 0;
session->foreach_audio_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
if (rec_enabled_diskstreams) {
frames /= rec_enabled_diskstreams;
@ -1431,7 +1431,7 @@ ARDOUR_UI::stop_blinking ()
void
ARDOUR_UI::add_diskstream_to_menu (AudioDiskstream& dstream)
ARDOUR_UI::add_diskstream_to_menu (Diskstream& dstream)
{
using namespace Gtk;
using namespace Menu_Helpers;
@ -1469,7 +1469,7 @@ ARDOUR_UI::select_diskstream (GdkEventButton *ev)
MenuList& items = diskstream_menu->items();
items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
session->foreach_audio_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
if (ev) {
diskstream_menu->popup (ev->button, ev->time);

View file

@ -546,7 +546,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode);
void session_add_midi_route (bool disk);
void add_diskstream_to_menu (ARDOUR::AudioDiskstream&);
void add_diskstream_to_menu (ARDOUR::Diskstream&);
void diskstream_selected (gint32);
Gtk::Menu *diskstream_menu;
gint32 selected_dstream;
@ -637,7 +637,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void toggle_monitor_enable (guint32);
uint32_t rec_enabled_diskstreams;
void count_recenabled_diskstreams (ARDOUR::AudioDiskstream&);
void count_recenabled_diskstreams (ARDOUR::Diskstream&);
About* about;
bool shown_flag;

View file

@ -76,7 +76,7 @@ ARDOUR_UI::connect_to_session (Session *s)
rec_button.set_sensitive (true);
shuttle_box.set_sensitive (true);
if (session->n_audio_diskstreams() == 0) {
if (session->n_diskstreams() == 0) {
session->DiskstreamAdded.connect (mem_fun(*this, &ARDOUR_UI::diskstream_added));
}

View file

@ -241,7 +241,6 @@ AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, Route& rt
map_frozen ();
} else {
/* bus */
controls_ebox.set_name ("BusControlsBaseUnselected");
@ -826,7 +825,7 @@ AudioTimeAxisView::rename_current_playlist ()
AudioPlaylist *pl;
AudioDiskstream *ds;
if (((ds = get_diskstream()) == 0) || ds->destructive()
if (((ds = dynamic_cast<AudioDiskstream*>(get_diskstream())) == 0) || ds->destructive()
|| ((pl = dynamic_cast<AudioPlaylist*>(ds->playlist())) == 0)) {
return;
}
@ -856,7 +855,7 @@ AudioTimeAxisView::use_copy_playlist (bool prompt)
AudioDiskstream *ds;
string name;
if (((ds = get_diskstream()) == 0) || ds->destructive()
if (((ds = dynamic_cast<AudioDiskstream*>(get_diskstream())) == 0) || ds->destructive()
|| ((pl = dynamic_cast<AudioPlaylist*>(ds->playlist())) == 0)) {
return;
}
@ -897,7 +896,7 @@ AudioTimeAxisView::use_new_playlist (bool prompt)
AudioDiskstream *ds;
string name;
if (((ds = get_diskstream()) == 0) || ds->destructive()
if (((ds = dynamic_cast<AudioDiskstream*>(get_diskstream())) == 0) || ds->destructive()
|| ((pl = dynamic_cast<AudioPlaylist*>(ds->playlist())) == 0)) {
return;
}
@ -936,7 +935,7 @@ AudioTimeAxisView::clear_playlist ()
AudioPlaylist *pl;
AudioDiskstream *ds;
if ((ds = get_diskstream()) != 0) {
if ((ds = dynamic_cast<AudioDiskstream*>(get_diskstream())) != 0) {
if ((pl = dynamic_cast<AudioPlaylist*>(ds->playlist())) != 0) {
editor.clear_playlist (*pl);
}
@ -994,7 +993,7 @@ AudioTimeAxisView::update_diskstream_display ()
{
AudioDiskstream *ds;
if ((ds = get_diskstream()) != 0) {
if ((ds = dynamic_cast<AudioDiskstream*>(get_diskstream())) != 0) {
set_playlist (dynamic_cast<AudioPlaylist*> (ds->playlist ()));
}
@ -1096,7 +1095,7 @@ AudioTimeAxisView::name() const
Playlist *
AudioTimeAxisView::playlist () const
{
AudioDiskstream *ds;
Diskstream *ds;
if ((ds = get_diskstream()) != 0) {
return ds->playlist();
@ -1143,10 +1142,16 @@ AudioTimeAxisView::hide_click ()
editor.hide_track_in_display (*this);
}
ARDOUR::AudioDiskstream*
AudioTimeAxisView::get_diskstream() const
{
return dynamic_cast<ARDOUR::AudioDiskstream*>(RouteUI::get_diskstream());
}
Region*
AudioTimeAxisView::find_next_region (jack_nframes_t pos, RegionPoint point, int32_t dir)
{
AudioDiskstream *stream;
Diskstream *stream;
Playlist *playlist;
if ((stream = get_diskstream()) != 0 && (playlist = stream->playlist()) != 0) {
@ -1721,7 +1726,7 @@ bool
AudioTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
{
Playlist* what_we_got;
AudioDiskstream* ds = get_diskstream();
AudioDiskstream* ds = dynamic_cast<AudioDiskstream*>(get_diskstream());
Playlist* playlist;
bool ret = false;

View file

@ -99,6 +99,8 @@ class AudioTimeAxisView : public RouteUI, public TimeAxisView
void hide_dependent_views (TimeAxisViewItem&);
void reveal_dependent_views (TimeAxisViewItem&);
ARDOUR::AudioDiskstream* get_diskstream() const;
ARDOUR::Region* find_next_region (jack_nframes_t pos, ARDOUR::RegionPoint, int32_t dir);
string name() const;

View file

@ -7,6 +7,9 @@ COLORID(cFrameBase)
COLORID(cAudioTrackBase)
COLORID(cAudioTrackOutline)
COLORID(cAudioBusBase)
COLORID(cMidiTrackBase)
COLORID(cMidiTrackOutline)
COLORID(cMidiBusBase)
COLORID(cTimeStretchFill)
COLORID(cTimeStretchOutline)
COLORID(cAutomationLine)

View file

@ -1599,7 +1599,7 @@ Editor::build_track_region_context_menu (jack_nframes_t frame)
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
if (atv) {
AudioDiskstream* ds;
Diskstream* ds;
Playlist* pl;
if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
@ -1626,7 +1626,7 @@ Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
if (atv) {
AudioDiskstream* ds;
Diskstream* ds;
Playlist* pl;
AudioPlaylist* apl;

View file

@ -20,9 +20,9 @@
#include <fft_result.h>
#include <fft_graph.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <cstdlib>
#include <string>
#include <cmath>
#include <iostream>

View file

@ -665,15 +665,16 @@ MixerStrip::select_stream_input ()
MenuList& items = stream_menu->items();
stream_menu->set_name ("ArdourContextMenu");
Session::AudioDiskstreamList streams = _session.audio_disk_streams();
Session::DiskstreamList streams = _session.disk_streams();
for (Session::AudioDiskstreamList::iterator i = streams.begin(); i != streams.end(); ++i) {
for (Session::DiskstreamList::iterator i = streams.begin(); i != streams.end(); ++i) {
AudioDiskstream* ads = dynamic_cast<AudioDiskstream*>(*i);
if (!(*i)->hidden()) {
if (ads && !(*i)->hidden()) {
items.push_back (CheckMenuElem ((*i)->name(), bind (mem_fun(*this, &MixerStrip::stream_input_chosen), *i)));
items.push_back (CheckMenuElem (ads->name(), bind (mem_fun(*this, &MixerStrip::stream_input_chosen), ads)));
if (get_diskstream() == *i) {
if (get_diskstream() == ads) {
ignore_toggle = true;
static_cast<CheckMenuItem *> (&items.back())->set_active (true);
ignore_toggle = false;

View file

@ -90,7 +90,7 @@ void
PlaylistSelector::show_for (RouteUI* ruix)
{
vector<const char*> item;
AudioDiskstream* this_ds;
Diskstream* this_ds;
string str;
rui = ruix;

View file

@ -27,7 +27,7 @@ print "Updating pot file: "
domain = gtkardour['DOMAIN']
potfile = gtkardour['POTFILE']
poaction = Action('intltool-update -p -g=' + domain)
poaction = env.Action('intltool-update -p -g=' + domain)
Execute(poaction)

View file

@ -1,5 +1,5 @@
/*
Copyright (C) 2002 Paul Davis
Copyright (C) 2002-2006 Paul Davis
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
@ -35,6 +35,8 @@
#include <ardour/route.h>
#include <ardour/audio_track.h>
#include <ardour/audio_diskstream.h>
#include <ardour/midi_track.h>
#include <ardour/midi_diskstream.h>
#include "i18n.h"
using namespace sigc;
@ -879,13 +881,22 @@ RouteUI::is_audio_track () const
return dynamic_cast<AudioTrack*>(&_route) != 0;
}
AudioDiskstream*
bool
RouteUI::is_midi_track () const
{
return dynamic_cast<MidiTrack*>(&_route) != 0;
}
Diskstream*
RouteUI::get_diskstream () const
{
AudioTrack *at;
MidiTrack *mt;
if ((at = dynamic_cast<AudioTrack*>(&_route)) != 0) {
return &at->disk_stream();
} else if ((mt = dynamic_cast<MidiTrack*>(&_route)) != 0) {
return &mt->disk_stream();
} else {
return 0;
}
@ -896,6 +907,13 @@ RouteUI::audio_track() const
{
return dynamic_cast<AudioTrack*>(&_route);
}
MidiTrack*
RouteUI::midi_track() const
{
return dynamic_cast<MidiTrack*>(&_route);
}
string
RouteUI::name() const
{

View file

@ -35,6 +35,7 @@ namespace Gtkmm2ext {
namespace ARDOUR {
class AudioTrack;
class MidiTrack;
}
namespace Gtk {
@ -50,10 +51,13 @@ class RouteUI : public virtual AxisView
virtual ~RouteUI();
bool is_audio_track() const;
ARDOUR::AudioDiskstream* get_diskstream() const;
bool is_midi_track() const;
//ARDOUR::AudioDiskstream* get_diskstream() const;
ARDOUR::Diskstream* get_diskstream() const;
ARDOUR::Route& route() const { return _route; }
ARDOUR::AudioTrack* audio_track() const;
ARDOUR::MidiTrack* midi_track() const;
string name() const;

View file

@ -39,10 +39,14 @@ StreamView::StreamView (AudioTimeAxisView& tv)
crossfades_visible = true;
if (tv.is_audio_track()) {
/* TRACK */
/* AUDIO TRACK */
//stream_base_color = RGBA_TO_UINT (222,223,218,255);
stream_base_color = color_map[cAudioTrackBase];
} else if (tv.is_midi_track()) {
/* MIDI TRACK */
stream_base_color = color_map[cMidiTrackBase];
} else {
// FIXME: distinction between audio and midi busses
/* BUS */
//stream_base_color = RGBA_TO_UINT (230,226,238,255);
stream_base_color = color_map[cAudioBusBase];

View file

@ -106,7 +106,7 @@ arch_specific_objects = [ ]
osc_files = [ 'osc.cc' ]
vst_files = [ 'vst_plugin.cc', 'session_vst.cc' ]
coreaudio_files = [ 'coreaudio_source.cc' ]
coreaudio_files = [ 'coreaudiosource.cc' ]
extra_sources = [ ]
if ardour['VST']:
@ -206,7 +206,7 @@ ardour.Merge ([
libraries['lrdf'],
libraries['samplerate'],
libraries['sigc2'],
libraries['pbd3'],
libraries['pbd'],
libraries['soundtouch'],
libraries['midi++2'],
libraries['glib2'],

View file

@ -42,7 +42,7 @@ class AudioFileSource : public AudioSource {
Removable = 0x8,
RemovableIfEmpty = 0x10,
RemoveAtDestroy = 0x20,
BuildPeaks = 0x40
NoPeakFile = 0x40
};
virtual ~AudioFileSource ();
@ -62,7 +62,7 @@ class AudioFileSource : public AudioSource {
cannot.
*/
static AudioFileSource* create (string path_plus_channel);
static AudioFileSource* create (const string& path_plus_channel, Flag flags = Flag (0));
static AudioFileSource* create (const XMLNode&);
static bool get_soundfile_info (string path, SoundFileInfo& _info, string& error);
@ -97,7 +97,7 @@ class AudioFileSource : public AudioSource {
static void set_search_path (string);
static void set_header_position_offset (jack_nframes_t offset, bool negative);
static sigc::signal<void,struct tm*, time_t> HeaderPositionOffsetChanged;
static sigc::signal<void> HeaderPositionOffsetChanged;
XMLNode& get_state ();
int set_state (const XMLNode&);
@ -107,7 +107,7 @@ class AudioFileSource : public AudioSource {
to cause issues.
*/
void handle_header_position_change (struct tm*, time_t tnow);
void handle_header_position_change ();
protected:

View file

@ -27,16 +27,23 @@ namespace ARDOUR {
class CoreAudioSource : public AudioFileSource {
public:
CoreAudioSource (const string& path_plus_channel, bool build_peak = true);
CoreAudioSource (const XMLNode&);
CoreAudioSource (const string& path_plus_channel, Flag);
~CoreAudioSource ();
float sample_rate() const;
int update_header (jack_nframes_t when, struct tm&, time_t);
int flush_header () {return 0;};
void set_header_timeline_position () {};
protected:
jack_nframes_t read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const;
jack_nframes_t write_unlocked (Sample *dst, jack_nframes_t cnt, char * workbuf)
{ return 0; }
private:
ExtAudioFileRef af;
uint16_t n_channels;
@ -45,7 +52,7 @@ class CoreAudioSource : public AudioFileSource {
mutable jack_nframes_t tmpbufsize;
mutable Glib::Mutex _tmpbuf_lock;
void init (const string &str, bool build_peak);
void init (const string &str);
};
}; /* namespace ARDOUR */

View file

@ -32,8 +32,7 @@ namespace ARDOUR {
class DestructiveFileSource : public SndFileSource {
public:
DestructiveFileSource (std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
Flag flags = AudioFileSource::Flag (AudioFileSource::Writable|
AudioFileSource::BuildPeaks));
Flag flags = AudioFileSource::Flag (AudioFileSource::Writable));
DestructiveFileSource (const XMLNode&);
~DestructiveFileSource ();

View file

@ -80,6 +80,9 @@ class Diskstream : public Stateful, public sigc::trackable
void unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; }
uint32_t refcnt() const { return _refcnt; }
virtual float playback_buffer_load() const = 0;
virtual float capture_buffer_load() const = 0;
void set_flag (Flag f) { _flags |= f; }
void unset_flag (Flag f) { _flags &= ~f; }
@ -106,6 +109,7 @@ class Diskstream : public Stateful, public sigc::trackable
virtual void punch_out() {}
virtual void set_speed (double);
virtual void non_realtime_set_speed () = 0;
virtual Playlist *playlist () = 0;
virtual int use_new_playlist () = 0;
@ -129,6 +133,9 @@ class Diskstream : public Stateful, public sigc::trackable
virtual XMLNode& get_state(void) = 0;
virtual int set_state(const XMLNode& node) = 0;
// FIXME: makes sense for all diskstream types?
virtual void monitor_input (bool) {}
jack_nframes_t capture_offset() const { return _capture_offset; }
virtual void set_capture_offset ();
@ -166,7 +173,7 @@ class Diskstream : public Stateful, public sigc::trackable
virtual void set_pending_overwrite (bool) = 0;
virtual int overwrite_existing_buffers () = 0;
virtual void reverse_scrub_buffer (bool to_forward) = 0;
//void set_block_size (jack_nframes_t);
virtual void set_block_size (jack_nframes_t) = 0;
virtual int internal_playback_seek (jack_nframes_t distance) = 0;
virtual int can_internal_playback_seek (jack_nframes_t distance) = 0;
virtual int rename_write_sources () = 0;

View file

@ -68,6 +68,7 @@ class AuxInput;
class Source;
class AudioSource;
class Diskstream;
class AudioDiskstream;
class AudioFileSource;
class Auditioner;
@ -281,23 +282,18 @@ class Session : public sigc::trackable, public Stateful
void refill_all_diskstream_buffers ();
uint32_t diskstream_buffer_size() const { return dstream_buffer_size; }
/* XXX fix required here when we get new diskstream types *, but
not sure of the direction to take this in until then.
*/
uint32_t get_next_diskstream_id() const { return n_diskstreams(); }
uint32_t n_diskstreams() const;
uint32_t get_next_diskstream_id() const { return n_audio_diskstreams(); }
uint32_t n_audio_diskstreams() const;
template<class T> void foreach_diskstream (T *obj, void (T::*func)(Diskstream&));
typedef list<AudioDiskstream *> AudioDiskstreamList;
typedef list<Diskstream *> DiskstreamList;
Session::AudioDiskstreamList audio_disk_streams() const {
Session::DiskstreamList disk_streams() const {
Glib::RWLock::ReaderLock lm (diskstream_lock);
return audio_diskstreams; /* XXX yes, force a copy */
return diskstreams; /* XXX yes, force a copy */
}
void foreach_audio_diskstream (void (AudioDiskstream::*func)(void));
template<class T> void foreach_audio_diskstream (T *obj, void (T::*func)(AudioDiskstream&));
typedef list<Route *> RouteList;
RouteList get_routes() const {
@ -719,8 +715,6 @@ class Session : public sigc::trackable, public Stateful
sigc::signal<void,Playlist*> PlaylistAdded;
sigc::signal<void,Playlist*> PlaylistRemoved;
Playlist *get_playlist (string name);
uint32_t n_playlists() const;
template<class T> void foreach_playlist (T *obj, void (T::*func)(Playlist *));
@ -980,7 +974,7 @@ class Session : public sigc::trackable, public Stateful
void set_frame_rate (jack_nframes_t nframes);
protected:
friend class AudioDiskstream;
friend class Diskstream;
void stop_butler ();
void wait_till_butler_finished();
@ -1475,7 +1469,7 @@ class Session : public sigc::trackable, public Stateful
/* disk-streams */
AudioDiskstreamList audio_diskstreams;
DiskstreamList diskstreams;
mutable Glib::RWLock diskstream_lock;
uint32_t dstream_buffer_size;
void add_diskstream (Diskstream*);

View file

@ -27,10 +27,10 @@
namespace ARDOUR {
template<class T> void
Session::foreach_audio_diskstream (T *obj, void (T::*func)(AudioDiskstream&))
Session::foreach_diskstream (T *obj, void (T::*func)(Diskstream&))
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); i++) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); i++) {
if (!(*i)->hidden()) {
(obj->*func) (**i);
}

View file

@ -39,8 +39,7 @@ class SndFileSource : public AudioFileSource {
Flag flags = AudioFileSource::Flag (AudioFileSource::Writable|
AudioFileSource::Removable|
AudioFileSource::RemovableIfEmpty|
AudioFileSource::CanRename|
AudioFileSource::BuildPeaks));
AudioFileSource::CanRename));
/* constructor to be called for existing in-session files */
@ -52,7 +51,7 @@ class SndFileSource : public AudioFileSource {
int update_header (jack_nframes_t when, struct tm&, time_t);
int flush_header ();
static Flag default_in_session_flags();
void handle_smpte_offset_change (jack_nframes_t offset, bool negative);
protected:
void set_header_timeline_position ();

View file

@ -55,10 +55,7 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
//sigc::signal<void,AudioDiskstream*> AudioDiskstream::AudioDiskstreamCreated;
sigc::signal<void,list<AudioFileSource*>*> AudioDiskstream::DeleteSources;
//sigc::signal<void> AudioDiskstream::DiskOverrun;
//sigc::signal<void> AudioDiskstream::DiskUnderrun;
AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream::Flag flag)
: Diskstream(sess, name, flag)
@ -295,9 +292,9 @@ AudioDiskstream::find_and_use_playlist (const string& name)
Playlist* pl;
AudioPlaylist* playlist;
if ((pl = _session.get_playlist (name)) == 0) {
error << string_compose(_("AudioDiskstream: Session doesn't know about a Playlist called \"%1\""), name) << endmsg;
return -1;
if ((pl = _session.playlist_by_name (name)) == 0) {
playlist = new AudioPlaylist(_session, name);
pl = playlist;
}
if ((playlist = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
@ -1630,6 +1627,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
srcs.push_back (s);
if ((fsrc = dynamic_cast<AudioFileSource *>(s)) != 0) {
cerr << "updating source after capture\n";
fsrc->update_header (capture_info.front()->start, when, twhen);
}

View file

@ -20,7 +20,7 @@
#include <algorithm>
#include <stdlib.h>
#include <cstdlib>
#include <sigc++/bind.h>

View file

@ -94,14 +94,6 @@ AudioTrack::~AudioTrack ()
}
}
#if 0
void
AudioTrack::handle_smpte_offset_change ()
{
diskstream
}
#endif
int
AudioTrack::deprecated_use_diskstream_connections ()
{

View file

@ -42,7 +42,7 @@
// if these headers come before sigc++ is included
// the parser throws ObjC++ errors. (nil is a keyword)
#ifdef HAVE_COREAUDIO
#include <ardour/coreaudio_source.h>
#include <ardour/coreaudiosource.h>
#include <AudioToolbox/ExtendedAudioFile.h>
#include <AudioToolbox/AudioFormat.h>
#endif // HAVE_COREAUDIO
@ -55,7 +55,7 @@ using namespace PBD;
string AudioFileSource::peak_dir = "";
string AudioFileSource::search_path;
sigc::signal<void,struct tm*, time_t> AudioFileSource::HeaderPositionOffsetChanged;
sigc::signal<void> AudioFileSource::HeaderPositionOffsetChanged;
bool AudioFileSource::header_position_negative;
uint64_t AudioFileSource::header_position_offset;
@ -122,7 +122,6 @@ AudioFileSource::init (string pathstr, bool must_exist)
next_peak_clear_should_notify = false;
if (!find (pathstr, must_exist, is_new)) {
cerr << "cannot find " << pathstr << " with me = " << must_exist << endl;
return -1;
}
@ -211,16 +210,16 @@ AudioFileSource::create (const XMLNode& node)
#ifdef HAVE_COREAUDIO
AudioFileSource*
AudioFileSource::create (const string& idstr)
AudioFileSource::create (const string& idstr, Flag flags)
{
AudioFileSource* es = 0;
try {
es = new CoreAudioSource (idstr);
es = new CoreAudioSource (idstr, flags);
}
catch (failed_constructor& err) {
es = new SndFileSource (idstr);
es = new SndFileSource (idstr, flags);
}
return es;
@ -229,9 +228,9 @@ AudioFileSource::create (const string& idstr)
#else
AudioFileSource*
AudioFileSource::create (string idstr)
AudioFileSource::create (const string& idstr, Flag flags)
{
return new SndFileSource (idstr);
return new SndFileSource (idstr, flags);
}
#endif // HAVE_COREAUDIO
@ -595,13 +594,19 @@ AudioFileSource::set_search_path (string p)
void
AudioFileSource::set_header_position_offset (jack_nframes_t offset, bool negative)
{
time_t tnow;
time (&tnow);
header_position_offset = offset;
header_position_negative = negative;
HeaderPositionOffsetChanged (localtime (&tnow), tnow); /* EMIT SIGNAL */
HeaderPositionOffsetChanged ();
}
void
AudioFileSource::handle_header_position_change ()
{
if (writable()) {
set_header_timeline_position ();
flush_header ();
}
}
void
@ -610,17 +615,6 @@ AudioFileSource::set_timeline_position (jack_nframes_t pos)
timeline_position = pos;
}
void
AudioFileSource::handle_header_position_change (struct tm* now, time_t tnow)
{
/* don't do this if the file has never had its header flushed to disk yet */
if (writable() && _timestamp) {
set_header_timeline_position ();
flush_header ();
}
}
void
AudioFileSource::set_allow_remove_if_empty (bool yn)
{
@ -655,8 +649,14 @@ AudioFileSource::set_name (string newname, bool destructive)
bool
AudioFileSource::is_empty (string path)
{
/* XXX fix me */
bool ret = false;
AudioFileSource* afs = create (path, NoPeakFile);
return false;
if (afs) {
ret = (afs->length() == 0);
delete afs;
}
return ret;
}

View file

@ -18,8 +18,7 @@
*/
#include <pbd/error.h>
#include <ardour/coreaudio_source.h>
#include <ardour/coreaudiosource.h>
#include "i18n.h"
@ -31,22 +30,21 @@ using namespace PBD;
CoreAudioSource::CoreAudioSource (const XMLNode& node)
: AudioFileSource (node)
{
init (_name, true);
init (_name);
AudioSourceCreated (this); /* EMIT SIGNAL */
}
CoreAudioSource::CoreAudioSource (const string& idstr, bool build_peak)
: AudioFileSource(idstr, build_peak)
CoreAudioSource::CoreAudioSource (const string& idstr, Flag flags)
: AudioFileSource(idstr, flags)
{
init (idstr, build_peak);
init (idstr);
if (build_peak) {
AudioSourceCreated (this); /* EMIT SIGNAL */
}
}
void
CoreAudioSource::init (const string& idstr, bool build_peak)
CoreAudioSource::init (const string& idstr)
{
string::size_type pos;
string file;
@ -132,7 +130,7 @@ CoreAudioSource::init (const string& idstr, bool build_peak)
throw failed_constructor ();
}
if (build_peak) {
if (_build_peakfiles) {
if (initialize_peakfile (false, file)) {
error << "initialize peakfile failed" << endmsg;
ExtAudioFileDispose (af);
@ -155,7 +153,7 @@ CoreAudioSource::~CoreAudioSource ()
}
jack_nframes_t
CoreAudioSource::read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const
CoreAudioSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const
{
OSStatus err = noErr;

View file

@ -55,10 +55,7 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
//sigc::signal<void,MidiDiskstream*> MidiDiskstream::MidiDiskstreamCreated;
sigc::signal<void,list<SMFSource*>*> MidiDiskstream::DeleteSources;
//sigc::signal<void> MidiDiskstream::DiskOverrun;
//sigc::signal<void> MidiDiskstream::DiskUnderrun;
MidiDiskstream::MidiDiskstream (Session &sess, const string &name, Diskstream::Flag flag)
: Diskstream(sess, name, flag)
@ -154,13 +151,13 @@ MidiDiskstream::find_and_use_playlist (const string& name)
Playlist* pl;
MidiPlaylist* playlist;
if ((pl = _session.get_playlist (name)) == 0) {
error << string_compose(_("MidiDiskstream: Session doesn't know about a Playlist called \"%1\""), name) << endmsg;
return -1;
if ((pl = _session.playlist_by_name (name)) == 0) {
playlist = new MidiPlaylist(_session, name);
pl = playlist;
}
if ((playlist = dynamic_cast<MidiPlaylist*> (pl)) == 0) {
error << string_compose(_("MidiDiskstream: Playlist \"%1\" isn't an midi playlist"), name) << endmsg;
error << string_compose(_("MidiDiskstream: Playlist \"%1\" isn't a midi playlist"), name) << endmsg;
return -1;
}

View file

@ -186,32 +186,30 @@ MidiTrack::set_diskstream (MidiDiskstream& ds, void *src)
int
MidiTrack::use_diskstream (string name)
{
/*
MidiDiskstream *dstream;
if ((dstream = _session.diskstream_by_name (name)) == 0) {
if ((dstream = dynamic_cast<MidiDiskstream*>(_session.diskstream_by_name (name))) == 0) {
PBD::error << string_compose(_("MidiTrack: diskstream \"%1\" not known by session"), name) << endmsg;
return -1;
}
return set_diskstream (*dstream, this);
*/
return 0;
}
int
MidiTrack::use_diskstream (id_t id)
{
/*
MidiDiskstream *dstream;
if ((dstream = _session.diskstream_by_id (id)) == 0) {
if ((dstream = dynamic_cast<MidiDiskstream*>(_session.diskstream_by_id (id))) == 0) {
PBD::error << string_compose(_("MidiTrack: diskstream \"%1\" not known by session"), id) << endmsg;
return -1;
}
return set_diskstream (*dstream, this);
*/
return 0;
}

View file

@ -127,10 +127,16 @@ Plugin::MIDIPortControl::set_value (float value)
value = 0.0;
}
} else {
value = lower + (range * value);
if (logarithmic) {
value = exp(value);
if (!logarithmic) {
value = lower + (range * value);
} else {
float _lower = 0.0f;
if (lower > 0.0f) {
_lower = log(lower);
}
value = exp(_lower + log(range) * value);
}
}

View file

@ -462,10 +462,10 @@ Session::~Session ()
}
#ifdef TRACK_DESTRUCTION
cerr << "delete audio_diskstreams\n";
cerr << "delete diskstreams\n";
#endif /* TRACK_DESTRUCTION */
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ) {
AudioDiskstreamList::iterator tmp;
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ) {
DiskstreamList::iterator tmp;
tmp = i;
++tmp;
@ -973,7 +973,7 @@ Session::set_auto_input (bool yn)
The rarity and short potential lock duration makes this "OK"
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (!auto_input);
@ -991,7 +991,7 @@ Session::reset_input_monitor_state ()
{
if (transport_rolling()) {
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (Config->get_use_hardware_monitoring() && !auto_input);
@ -999,7 +999,7 @@ Session::reset_input_monitor_state ()
}
} else {
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (Config->get_use_hardware_monitoring());
@ -1080,7 +1080,7 @@ Session::auto_loop_changed (Location* location)
}
else if (seamless_loop && !loop_changing) {
// schedule a locate-roll to refill the audio_diskstreams at the
// schedule a locate-roll to refill the diskstreams at the
// previous loop end
loop_changing = true;
@ -1277,7 +1277,7 @@ Session::enable_record ()
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
(*i)->monitor_input (true);
}
@ -1316,7 +1316,7 @@ Session::disable_record (bool rt_context, bool force)
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
(*i)->monitor_input (false);
}
@ -1343,7 +1343,7 @@ Session::step_back_from_record ()
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if (auto_input && (*i)->record_enabled ()) {
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (false);
@ -1512,7 +1512,7 @@ Session::set_block_size (jack_nframes_t nframes)
(*i)->set_block_size (nframes);
}
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
(*i)->set_block_size (nframes);
}
@ -2115,21 +2115,14 @@ Session::add_route (Route* route)
}
void
Session::add_diskstream (Diskstream* s)
Session::add_diskstream (Diskstream* dstream)
{
// FIXME: temporary. duh.
AudioDiskstream* dstream = dynamic_cast<AudioDiskstream*>(s);
if (!dstream) {
cerr << "FIXME: Non Audio Diskstream" << endl;
return;
}
/* need to do this in case we're rolling at the time, to prevent false underruns */
dstream->non_realtime_do_refill();
{
Glib::RWLock::WriterLock lm (diskstream_lock);
audio_diskstreams.push_back (dstream);
diskstreams.push_back (dstream);
}
/* take a reference to the diskstream, preventing it from
@ -2194,7 +2187,7 @@ Session::remove_route (Route& route)
{
Glib::RWLock::WriterLock lm (diskstream_lock);
audio_diskstreams.remove (ds);
diskstreams.remove (ds);
}
ds->unref ();
@ -2483,7 +2476,7 @@ Session::get_maximum_extent () const
ensure atomicity.
*/
for (AudioDiskstreamList::const_iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
Playlist* pl = (*i)->playlist();
if ((me = pl->get_maximum_extent()) > max) {
max = me;
@ -2499,7 +2492,7 @@ Session::diskstream_by_name (string name)
Glib::RWLock::ReaderLock lm (diskstream_lock);
// FIXME: duh
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->name() == name) {
return* i;
}
@ -2514,7 +2507,7 @@ Session::diskstream_by_id (id_t id)
Glib::RWLock::ReaderLock lm (diskstream_lock);
// FIXME: duh
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->id() == id) {
return *i;
}
@ -2840,7 +2833,7 @@ Session::remove_last_capture ()
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
list<Region*>& l = (*i)->last_capture_regions();
if (!l.empty()) {
@ -3151,18 +3144,6 @@ Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bo
/* Playlist management */
Playlist *
Session::get_playlist (string name)
{
Playlist* ret = 0;
if ((ret = playlist_by_name (name)) == 0) {
ret = new AudioPlaylist (*this, name);
}
return ret;
}
Playlist *
Session::playlist_by_name (string name)
{
@ -3385,29 +3366,30 @@ Session::set_all_mute (bool yn)
}
uint32_t
Session::n_audio_diskstreams () const
Session::n_diskstreams () const
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
uint32_t n = 0;
for (AudioDiskstreamList::const_iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
n++;
}
}
return n;
}
/*
void
Session::foreach_audio_diskstream (void (AudioDiskstream::*func)(void))
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
((*i)->*func)();
}
}
}
*/
void
Session::graph_reordered ()
@ -3429,7 +3411,7 @@ Session::graph_reordered ()
reflect any changes in latencies within the graph.
*/
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
(*i)->set_capture_offset ();
}
}
@ -3712,7 +3694,7 @@ Session::reset_native_file_format ()
//RWLockMonitor lm1 (route_lock, true, __LINE__, __FILE__);
Glib::RWLock::ReaderLock lm2 (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
(*i)->reset_write_sources (false);
}
}

View file

@ -168,7 +168,7 @@ Session::butler_thread_work ()
struct timeval begin, end;
struct pollfd pfd[1];
bool disk_work_outstanding = false;
AudioDiskstreamList::iterator i;
DiskstreamList::iterator i;
butler_mixdown_buffer = new Sample[AudioDiskstream::disk_io_frames()];
butler_gain_buffer = new gain_t[AudioDiskstream::disk_io_frames()];
@ -239,7 +239,7 @@ Session::butler_thread_work ()
}
}
//for (i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
//for (i = diskstreams.begin(); i != diskstreams.end(); ++i) {
// cerr << "BEFORE " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl;
//}
@ -255,15 +255,17 @@ Session::butler_thread_work ()
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (i = audio_diskstreams.begin(); !transport_work_requested() && butler_should_run && i != audio_diskstreams.end(); ++i) {
for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) {
// cerr << "rah fondr " << (*i)->io()->name () << endl;
AudioDiskstream* ads = dynamic_cast<AudioDiskstream*>(*i);
if (!ads) continue; // FIXME
switch ((*i)->do_refill (butler_mixdown_buffer, butler_gain_buffer, conv_buffer)) {
switch (ads->do_refill (butler_mixdown_buffer, butler_gain_buffer, conv_buffer)) {
case 0:
bytes += (*i)->read_data_count();
bytes += ads->read_data_count();
break;
case 1:
bytes += (*i)->read_data_count();
bytes += ads->read_data_count();
disk_work_outstanding = true;
break;
@ -275,7 +277,7 @@ Session::butler_thread_work ()
}
if (i != audio_diskstreams.end()) {
if (i != diskstreams.end()) {
/* we didn't get to all the streams */
disk_work_outstanding = true;
}
@ -297,7 +299,7 @@ Session::butler_thread_work ()
compute_io = true;
gettimeofday (&begin, 0);
for (i = audio_diskstreams.begin(); !transport_work_requested() && butler_should_run && i != audio_diskstreams.end(); ++i) {
for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) {
// cerr << "write behind for " << (*i)->name () << endl;
switch ((*i)->do_flush (conv_buffer)) {
@ -326,7 +328,7 @@ Session::butler_thread_work ()
request_stop ();
}
if (i != audio_diskstreams.end()) {
if (i != diskstreams.end()) {
/* we didn't get to all the streams */
disk_work_outstanding = true;
}
@ -353,7 +355,7 @@ Session::butler_thread_work ()
Glib::Mutex::Lock lm (butler_request_lock);
if (butler_should_run && (disk_work_outstanding || transport_work_requested())) {
// for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
// for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
// cerr << "AFTER " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl;
// }
@ -393,7 +395,7 @@ Session::overwrite_some_buffers (Diskstream* ds)
} else {
Glib::RWLock::ReaderLock dm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
(*i)->set_pending_overwrite (true);
}
}

View file

@ -495,7 +495,7 @@ Session::prepare_to_export (AudioExportSpecification& spec)
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)-> seek (spec.start_frame, true)) {
error << string_compose (_("%1: cannot seek to %2 for export"),
(*i)->name(), spec.start_frame)

View file

@ -74,7 +74,7 @@ Session::process (jack_nframes_t nframes)
void
Session::prepare_diskstreams ()
{
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
(*i)->prepare ();
}
}
@ -151,7 +151,7 @@ Session::process_routes (jack_nframes_t nframes, jack_nframes_t offset)
call path, so make sure we release any outstanding locks here before we return failure.
*/
for (AudioDiskstreamList::iterator ids = audio_diskstreams.begin(); ids != audio_diskstreams.end(); ++ids) {
for (DiskstreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) {
(*ids)->recover ();
}
@ -190,7 +190,7 @@ Session::silent_process_routes (jack_nframes_t nframes, jack_nframes_t offset)
call path, so make sure we release any outstanding locks here before we return failure.
*/
for (AudioDiskstreamList::iterator ids = audio_diskstreams.begin(); ids != audio_diskstreams.end(); ++ids) {
for (DiskstreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) {
(*ids)->recover ();
}
@ -209,7 +209,7 @@ Session::commit_diskstreams (jack_nframes_t nframes, bool &needs_butler)
float pworst = 1.0f;
float cworst = 1.0f;
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->hidden()) {
continue;
@ -579,7 +579,7 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
bool ok = true;
jack_nframes_t frame_delta = slave_transport_frame - _transport_frame;
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if (!(*i)->can_internal_playback_seek (frame_delta)) {
ok = false;
break;
@ -587,7 +587,7 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
}
if (ok) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
(*i)->internal_playback_seek (frame_delta);
}
_transport_frame += frame_delta;

View file

@ -59,6 +59,7 @@
#include <ardour/configuration.h>
#include <ardour/session.h>
#include <ardour/audio_diskstream.h>
#include <ardour/midi_diskstream.h>
#include <ardour/utils.h>
#include <ardour/audioplaylist.h>
#include <ardour/audiofilesource.h>
@ -270,7 +271,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
AudioSource::AudioSourceCreated.connect (mem_fun (*this, &Session::add_audio_source));
Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
AudioDiskstream::DiskstreamCreated.connect (mem_fun (*this, &Session::add_diskstream));
Diskstream::DiskstreamCreated.connect (mem_fun (*this, &Session::add_diskstream));
NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers));
@ -624,12 +625,16 @@ Session::load_diskstreams (const XMLNode& node)
clist = node.children();
for (citer = clist.begin(); citer != clist.end(); ++citer) {
AudioDiskstream* dstream;
Diskstream* dstream = NULL;
try {
if ((*citer)->name() == "AudioDiskstream") {
dstream = new AudioDiskstream (*this, **citer);
/* added automatically by AudioDiskstreamCreated handler */
/* added automatically by DiskstreamCreated handler */
} else {
assert((*citer)->name() == "MidiDiskstream");
dstream = new MidiDiskstream (*this, **citer);
}
}
catch (failed_constructor& err) {
@ -1380,7 +1385,7 @@ Session::state(bool full_state)
{
Glib::RWLock::ReaderLock dl (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
child->add_child_nocopy ((*i)->get_state());
}

View file

@ -113,7 +113,6 @@ Session::set_smpte_offset_negative (bool neg)
SMPTEOffsetChanged (); /* EMIT SIGNAL */
}
void
Session::smpte_to_sample( SMPTE::Time& smpte, jack_nframes_t& sample, bool use_offset, bool use_subframes ) const
{

View file

@ -206,7 +206,7 @@ Session::butler_transport_work ()
}
if (post_transport_work & PostTransportInputChange) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
(*i)->non_realtime_input_change ();
}
}
@ -222,7 +222,7 @@ Session::butler_transport_work ()
cumulative_rf_motion = 0;
reset_rf_scale (0);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
(*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
@ -254,7 +254,7 @@ Session::non_realtime_set_speed ()
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
(*i)->non_realtime_set_speed ();
}
}
@ -264,7 +264,7 @@ Session::non_realtime_overwrite ()
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->pending_overwrite) {
(*i)->overwrite_existing_buffers ();
}
@ -280,7 +280,7 @@ Session::non_realtime_stop (bool abort)
did_record = false;
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->get_captured_frames () != 0) {
did_record = true;
break;
@ -333,7 +333,7 @@ Session::non_realtime_stop (bool abort)
_have_captured = true;
}
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
(*i)->transport_stopped (*now, xnow, abort);
}
@ -370,7 +370,7 @@ Session::non_realtime_stop (bool abort)
}
#endif
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
(*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
@ -494,7 +494,7 @@ Session::set_auto_loop (bool yn)
if (seamless_loop) {
// set all diskstreams to use internal looping
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
(*i)->set_loop (loc);
}
@ -502,7 +502,7 @@ Session::set_auto_loop (bool yn)
}
else {
// set all diskstreams to NOT use internal looping
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
(*i)->set_loop (0);
}
@ -532,7 +532,7 @@ Session::set_auto_loop (bool yn)
clear_events (Event::AutoLoop);
// set all diskstreams to NOT use internal looping
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
(*i)->set_loop (0);
}
@ -653,7 +653,7 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b
The rarity and short potential lock duration makes this "OK"
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (!auto_input);
@ -668,7 +668,7 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b
The rarity and short potential lock duration makes this "OK"
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (true);
@ -714,7 +714,7 @@ Session::set_transport_speed (float speed, bool abort)
The rarity and short potential lock duration makes this "OK"
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (true);
@ -740,7 +740,7 @@ Session::set_transport_speed (float speed, bool abort)
The rarity and short potential lock duration makes this "OK"
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if (auto_input && (*i)->record_enabled ()) {
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (false);
@ -791,7 +791,7 @@ Session::set_transport_speed (float speed, bool abort)
_last_transport_speed = _transport_speed;
_transport_speed = speed;
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
}
@ -881,7 +881,7 @@ Session::actually_start_transport ()
transport_sub_state |= PendingDeclickIn;
_transport_speed = 1.0;
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
(*i)->realtime_set_speed ((*i)->speed(), true);
}
@ -1014,7 +1014,7 @@ Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
_slave_type = src;
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
non_rt_required = true;
@ -1242,7 +1242,7 @@ Session::update_latency_compensation (bool with_stop, bool abort)
/* reflect any changes in latencies into capture offsets
*/
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
(*i)->set_capture_offset ();
}
}

View file

@ -55,6 +55,7 @@ SndFileSource::SndFileSource (const XMLNode& node)
}
SndFileSource::SndFileSource (string idstr, Flag flags)
/* files created this way are never writable or removable */
: AudioFileSource (idstr, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
{
init (idstr);
@ -63,7 +64,7 @@ SndFileSource::SndFileSource (string idstr, Flag flags)
throw failed_constructor ();
}
if (_build_peakfiles) {
if (!(_flags & NoPeakFile) && _build_peakfiles) {
if (initialize_peakfile (false, _path)) {
sf_close (sf);
sf = 0;
@ -170,9 +171,10 @@ SndFileSource::SndFileSource (string idstr, SampleFormat sfmt, HeaderFormat hf,
delete _broadcast_info;
_broadcast_info = 0;
}
}
if (_build_peakfiles) {
if (!(_flags & NoPeakFile) && _build_peakfiles) {
if (initialize_peakfile (true, _path)) {
sf_close (sf);
sf = 0;
@ -180,12 +182,6 @@ SndFileSource::SndFileSource (string idstr, SampleFormat sfmt, HeaderFormat hf,
}
}
/* since SndFileSource's constructed with this constructor can be writable, make sure we update if the header info changes */
if (writable()) {
HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioFileSource::handle_header_position_change));
}
AudioSourceCreated (this); /* EMIT SIGNAL */
}
@ -235,34 +231,56 @@ SndFileSource::open ()
_length = _info.frames;
_broadcast_info = (SF_BROADCAST_INFO*) calloc (1, sizeof (SF_BROADCAST_INFO));
/* lookup broadcast info */
if (sf_command (sf, SFC_GET_BROADCAST_INFO, _broadcast_info, sizeof (*_broadcast_info)) != SF_TRUE) {
/* if the file has data but no broadcast info, then clearly, there is no broadcast info */
if (_length) {
free (_broadcast_info);
_broadcast_info = 0;
_flags = Flag (_flags & ~Broadcast);
}
} else {
/* XXX 64 bit alert: when JACK switches to a 64 bit frame count, this needs to use the high bits
of the time reference.
*/
set_timeline_position (_broadcast_info->time_reference_low);
}
if (writable()) {
sf_command (sf, SFC_SET_UPDATE_HEADER_AUTO, 0, SF_FALSE);
/* update header if header offset info changes */
AudioFileSource::HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioFileSource::handle_header_position_change));
}
return 0;
}
void
SndFileSource::close ()
{
if (sf) {
sf_close (sf);
sf = 0;
}
}
SndFileSource::~SndFileSource ()
{
GoingAway (this); /* EMIT SIGNAL */
close ();
if (sf) {
sf_close (sf);
sf = 0;
}
if (interleave_buf) {
delete [] interleave_buf;
}
if (_broadcast_info) {
delete [] _broadcast_info;
free (_broadcast_info);
}
}
@ -404,27 +422,38 @@ SndFileSource::write_unlocked (Sample *data, jack_nframes_t cnt, char * workbuf)
int
SndFileSource::update_header (jack_nframes_t when, struct tm& now, time_t tnow)
{
/* allow derived classes to override how this is done */
set_timeline_position (when);
if (_flags & Broadcast) {
/* this will flush the header implicitly */
return setup_broadcast_info (when, now, tnow);
} else {
return flush_header ();
if (setup_broadcast_info (when, now, tnow)) {
return -1;
}
}
return flush_header ();
}
int
SndFileSource::flush_header ()
{
if (!writable() || (sf == 0)) {
return -1;
}
return (sf_command (sf, SFC_UPDATE_HEADER_NOW, 0, 0) != SF_TRUE);
}
int
SndFileSource::setup_broadcast_info (jack_nframes_t when, struct tm& now, time_t tnow)
{
if (!writable()) {
return -1;
}
if (!(_flags & Broadcast)) {
return 0;
}
/* random code is 9 digits */
int random_code = random() % 999999999;
@ -452,12 +481,10 @@ SndFileSource::setup_broadcast_info (jack_nframes_t when, struct tm& now, time_t
set_header_timeline_position ();
/* note that libsndfile flushes the header to disk when resetting the broadcast info */
if (sf_command (sf, SFC_SET_BROADCAST_INFO, _broadcast_info, sizeof (*_broadcast_info)) != SF_TRUE) {
error << string_compose (_("cannot set broadcast info for audio file %1; Dropping broadcast info for this file"), _path) << endmsg;
_flags = Flag (_flags & ~Broadcast);
delete _broadcast_info;
free (_broadcast_info);
_broadcast_info = 0;
return -1;
}
@ -470,6 +497,10 @@ SndFileSource::set_header_timeline_position ()
{
uint64_t pos;
if (!(_flags & Broadcast)) {
return;
}
_broadcast_info->time_reference_high = 0;
if (header_position_negative) {
@ -491,6 +522,13 @@ SndFileSource::set_header_timeline_position ()
_broadcast_info->time_reference_high = (pos >> 32);
_broadcast_info->time_reference_low = (pos & 0xffffffff);
if (sf_command (sf, SFC_SET_BROADCAST_INFO, _broadcast_info, sizeof (*_broadcast_info)) != SF_TRUE) {
error << string_compose (_("cannot set broadcast info for audio file %1; Dropping broadcast info for this file"), _path) << endmsg;
_flags = Flag (_flags & ~Broadcast);
free (_broadcast_info);
_broadcast_info = 0;
}
}
jack_nframes_t

View file

@ -1,3 +0,0 @@
ClReader-lex.cc
ClReader.cc
ClReader.cc.h

View file

@ -1,37 +0,0 @@
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.

View file

@ -1,12 +0,0 @@
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

View file

@ -1,444 +0,0 @@
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

File diff suppressed because it is too large Load diff

View file

@ -1,23 +0,0 @@
// $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

View file

@ -1,102 +0,0 @@
// $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

View file

@ -1,21 +0,0 @@
#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>
*/

View file

@ -1,130 +0,0 @@
/* $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();
}

View file

@ -1,32 +0,0 @@
// $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

View file

@ -1,12 +0,0 @@
// $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

View file

@ -1,140 +0,0 @@
// $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;
}

View file

@ -1,29 +0,0 @@
// $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

View file

@ -1,364 +0,0 @@
// $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);
}

View file

@ -1,27 +0,0 @@
// $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

View file

@ -1,25 +0,0 @@
// $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

View file

@ -1,473 +0,0 @@
// $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>;

View file

@ -1,87 +0,0 @@
/* $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"); }

View file

@ -1,154 +0,0 @@
/*
$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;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,12 +0,0 @@
// $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

View file

@ -1,59 +0,0 @@
// $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); }

View file

@ -1,52 +0,0 @@
// $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)
{
}

View file

@ -1,149 +0,0 @@
// $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;
}

View file

@ -1,297 +0,0 @@
// $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

View file

@ -1,884 +0,0 @@
// $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;
}
}

View file

@ -1,21 +0,0 @@
// $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));

View file

@ -1,26 +0,0 @@
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/

View file

@ -1,18 +0,0 @@
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

View file

@ -1,229 +0,0 @@
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

View file

@ -1,241 +0,0 @@
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.

View file

@ -1,32 +0,0 @@
# -*- python -*-
Import('env libraries')
cassowary = env.Copy(YACCFLAGS="-d")
domain = 'libcassowary'
cassowary.Append(DOMAIN=domain,MAJOR=0,MINOR=60,MICRO=3)
cassowary_files = Split("""
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.cc
ClReader-lex.cc
""")
cassowary.Append(CCFLAGS="-D_REENTRANT")
cassowary.CXXFile(target = ['ClReader.cc', 'ClReader.cc.h'], source = 'ClReader.yy')
cassowary.CXXFile(target = 'ClReader-lex.cc', source = 'ClReader.ll')
libcassowary = cassowary.SharedLibrary('cassowary', cassowary_files)
Default(libcassowary)

View file

@ -1,30 +0,0 @@
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

View file

@ -1,102 +0,0 @@
#!/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

View file

@ -1,84 +0,0 @@
# 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

View file

@ -1,78 +0,0 @@
# 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

View file

@ -1,40 +0,0 @@
// $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

View file

@ -1,49 +0,0 @@
// $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

View file

@ -1,161 +0,0 @@
// $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

View file

@ -1,198 +0,0 @@
// $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

View file

@ -1,39 +0,0 @@
// $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

View file

@ -1,88 +0,0 @@
// $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

View file

@ -1,45 +0,0 @@
// $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

View file

@ -1,51 +0,0 @@
// $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

View file

@ -1,179 +0,0 @@
// $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

View file

@ -1,94 +0,0 @@
// $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

View file

@ -1,89 +0,0 @@
// $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

View file

@ -1,40 +0,0 @@
// $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

View file

@ -1,120 +0,0 @@
// $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

View file

@ -1,126 +0,0 @@
// $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

View file

@ -1,119 +0,0 @@
// $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

View file

@ -1,61 +0,0 @@
// $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

View file

@ -1,74 +0,0 @@
// $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

View file

@ -1,298 +0,0 @@
// $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

View file

@ -1,26 +0,0 @@
// $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

View file

@ -1,167 +0,0 @@
// $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

View file

@ -1,63 +0,0 @@
// $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

View file

@ -1,74 +0,0 @@
// $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

Some files were not shown because too many files have changed in this diff Show more