mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-10 00:34:59 +01:00
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:
parent
5dc4abef79
commit
22c20ab6f2
200 changed files with 5920 additions and 12700 deletions
98
SConstruct
98
SConstruct
|
|
@ -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')
|
||||
|
||||
#
|
||||
|
|
|
|||
|
|
@ -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'))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ COLORID(cFrameBase)
|
|||
COLORID(cAudioTrackBase)
|
||||
COLORID(cAudioTrackOutline)
|
||||
COLORID(cAudioBusBase)
|
||||
COLORID(cMidiTrackBase)
|
||||
COLORID(cMidiTrackOutline)
|
||||
COLORID(cMidiBusBase)
|
||||
COLORID(cTimeStretchFill)
|
||||
COLORID(cTimeStretchOutline)
|
||||
COLORID(cAutomationLine)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ void
|
|||
PlaylistSelector::show_for (RouteUI* ruix)
|
||||
{
|
||||
vector<const char*> item;
|
||||
AudioDiskstream* this_ds;
|
||||
Diskstream* this_ds;
|
||||
string str;
|
||||
|
||||
rui = ruix;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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'],
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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*);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <sigc++/bind.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -94,14 +94,6 @@ AudioTrack::~AudioTrack ()
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
AudioTrack::handle_smpte_offset_change ()
|
||||
{
|
||||
diskstream
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
AudioTrack::deprecated_use_diskstream_connections ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
ClReader-lex.cc
|
||||
ClReader.cc
|
||||
ClReader.cc.h
|
||||
|
|
@ -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.
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
*/
|
||||
|
||||
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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>;
|
||||
|
|
@ -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"); }
|
||||
|
||||
|
|
@ -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 = ξ
|
||||
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
|
|
@ -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
|
||||
|
|
@ -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); }
|
||||
|
||||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
|
||||
|
|
@ -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/
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue