// -*- coding: utf-8 -*-
// Copyright (C) 2013, 2014 Laboratoire de Recherche et Développement
// de l'Epita (LRDE).
//
// 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 3 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 this program. If not, see .
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "bitvect.hh"
#include
#include
#include
#include
#include
#include
namespace spot
{
namespace
{
// How many block_t do we need to store BITCOUNT bits?
size_t block_needed(size_t bitcount)
{
const size_t bpb = 8 * sizeof(bitvect::block_t);
size_t n = (bitcount + bpb - 1) / bpb;
if (n < 1)
return 1;
return n;
}
// Fowler-Noll-Vo hash parameters.
// Add specializations as needed.
template
struct fnv
{
};
// Do not define the following if ULONG_MAX cannot
// hold a 64-bit value, otherwise the parser will
// choke when parsing the constants.
#if ULONG_MAX >> 31 >> 31 >> 1 > 0
// Fowler-Noll-Vo hash parameters for 64bits
template<>
struct fnv<8>
{
static unsigned long init()
{
return 14695981039346656037UL;
}
static unsigned long prime()
{
return 1099511628211UL;
}
};
#endif
// Fowler-Noll-Vo hash parameters for 32bits
template<>
struct fnv<4>
{
static unsigned long init()
{
return 2166136261UL;
}
static unsigned long prime()
{
return 16777619UL;
}
};
}
bitvect::bitvect(size_t size, size_t block_count):
size_(size),
block_count_(block_count),
storage_(&local_storage_)
{
clear_all();
}
bitvect::bitvect(size_t size, size_t block_count, bool):
size_(size),
block_count_(block_count),
storage_(&local_storage_)
{
}
bitvect* bitvect::clone() const
{
size_t n = block_needed(size_);
// Allocate some memory for the bitvect. The instance
// already contains one int of local_storage_, but
// we allocate n-1 more so that we store the table.
void* mem = operator new(sizeof(bitvect)
+ (n - 1) * sizeof(bitvect::block_t));
bitvect* res = new(mem) bitvect(size_, n, true);
memcpy(res->storage_, storage_, res->block_count_ * sizeof(block_t));
return res;
}
size_t bitvect::hash() const
{
block_t res = fnv::init();
size_t i;
size_t m = used_blocks();
if (m == 0)
return res;
for (i = 0; i < m - 1; ++i)
{
res ^= storage_[i];
res *= fnv::prime();
}
// Deal with the last block, that might not be fully used.
// Compute the number n of bits used in the last block.
const size_t bpb = 8 * sizeof(bitvect::block_t);
size_t n = size() % bpb;
// Use only the least n bits from storage_[i].
res ^= storage_[i] & ((1UL << n) - 1);
return res;
}
bitvect* make_bitvect(size_t bitcount)
{
size_t n = block_needed(bitcount);
// Allocate some memory for the bitvect. The instance
// already contains one int of local_storage_, but
// we allocate n-1 more so that we store the table.
void* mem = operator new(sizeof(bitvect)
+ (n - 1) * sizeof(bitvect::block_t));
return new(mem) bitvect(bitcount, n);
}
bitvect_array* make_bitvect_array(size_t bitcount, size_t vectcount)
{
size_t n = block_needed(bitcount);
// Size of one bitvect.
size_t bvsize = sizeof(bitvect) + (n - 1) * sizeof(bitvect::block_t);
// Allocate the bitvect_array with enough space at the end
// to store all bitvect instances.
void* mem = operator new(sizeof(bitvect_array) + bvsize * vectcount);
bitvect_array* bva = new(mem) bitvect_array(vectcount, bvsize);
// Initialize all the bitvect instances.
for (size_t i = 0; i < vectcount; ++i)
new(bva->storage_ + i * bvsize) bitvect(bitcount, n);
return bva;
}
std::ostream& operator<<(std::ostream& os , const bitvect& v)
{
for (size_t i = 0, end = v.size(); i != end; ++i)
os << (v.get(i) ? '1' : '0');
return os;
}
std::ostream& operator<<(std::ostream& os , const bitvect_array& a)
{
size_t end = a.size();
if (end == 0)
{
os << "empty\n";
return os;
}
int w = floor(log10(end - 1)) + 1;
for (size_t i = 0; i != end; ++i)
{
os.width(w);
os << i;
os.width(1);
os << ": " << a.at(i) << '\n';
}
return os;
}
}