* src/misc/modgray.hh, src/misc/modgray.cc: New files.

* src/misc/Makefile.am (libmisc_la_SOURCES, misc_HEADERS): Add them.
* wrap/python/spot.i: Activate directors, and interface modgray.hh.
* wrap/python/tests/modgray.py: New file.
* wrap/python/tests/Makefile.am (TESTS): Add it.
This commit is contained in:
Alexandre Duret-Lutz 2004-10-20 15:46:56 +00:00
parent 7d27fd3796
commit 094ddca665
7 changed files with 351 additions and 2 deletions

130
src/misc/modgray.cc Normal file
View file

@ -0,0 +1,130 @@
// Copyright (C) 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
// et Marie Curie.
//
// This file is part of Spot, a model checking library.
//
// Spot is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// Spot is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
// License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Spot; see the file COPYING. If not, write to the Free
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
#include "modgray.hh"
namespace spot
{
loopless_modular_mixed_radix_gray_code::
loopless_modular_mixed_radix_gray_code(int n)
: n_(n), a_(0), f_(0), m_(0), s_(0), non_one_radixes_(0)
{
}
loopless_modular_mixed_radix_gray_code::
~loopless_modular_mixed_radix_gray_code()
{
delete[] a_;
delete[] f_;
delete[] m_;
delete[] s_;
delete[] non_one_radixes_;
}
void
loopless_modular_mixed_radix_gray_code::first()
{
if (!non_one_radixes_)
{
// This computation needs to be done only once, but we cannot
// do it in the constructor because it involves virtual
// functions.
// non_one_radixes_ needs to hold at most n_ integer, maybe less
// we do not know yet and do not care (saving these extra bytes
// would require two loops over a_last(j); this doesn't seem
// worth the hassle). We update n_ before allocating the other
// arrays.
non_one_radixes_ = new int[n_];
int k = 0;
for (int j = 0; j < n_; ++j)
{
a_first(j);
if (!a_last(j))
non_one_radixes_[k++] = j;
}
n_ = k;
a_ = new int[k];
f_ = new int[k + 1];
m_ = new int[k];
s_ = new int[k];
for (int j = 0; j < n_; ++j)
m_[j] = -1;
f_[n_] = n_;
}
// Reset everything except m_[j] (let's preserve discovered
// radixes between runs) and f_[n_] (never changes).
for (int j = 0; j < n_; ++j)
{
a_[j] = 0;
a_first(non_one_radixes_[j]);
s_[j] = m_[j];
f_[j] = j;
}
done_ = false;
}
// Update one item of the tuple and return its position.
int
loopless_modular_mixed_radix_gray_code::next()
{
int j = f_[0];
if (j == n_)
{
done_ = true;
return -1;
}
f_[0] = 0;
int real_j = non_one_radixes_[j];
if (a_[j] == m_[j])
{
a_[j] = 0;
a_first(real_j);
}
else
{
++a_[j];
a_next(real_j);
// Discover the radix on-the-fly.
if (m_[j] == -1 && a_last(real_j))
s_[j] = m_[j] = a_[j];
}
if (a_[j] == s_[j])
{
--s_[j];
if (s_[j] < 0)
s_[j] = m_[j];
f_[j] = f_[j + 1];
f_[j + 1] = j + 1;
}
return real_j;
}
} // spot