Files
secondo/Algebras/Collection/IntSet.cpp
2026-01-23 17:03:45 +08:00

471 lines
10 KiB
C++

/*
----
This file is part of SECONDO.
Copyright (C) 2019,
University in Hagen,
Faculty of Mathematics and Computer Science,
Database Systems for New Applications.
SECONDO 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.
SECONDO 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 SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----
*/
#include "IntSet.h"
#include "Attribute.h"
#include <set>
#include <iostream>
#include "NestedList.h"
extern NestedList* nl;
namespace collection{
IntSet::IntSet(const IntSet& src):Attribute(src),value(0),size(src.size){
if(size>0){
value = new int[size];
memcpy((char*)value, src.value,size*sizeof(int));
}
}
IntSet::IntSet(IntSet&& src): Attribute(src),
value(src.value), size(src.size) {
src.size = 0;
src.value = 0;
}
IntSet::IntSet(const std::set<int>& src):Attribute(true), value(0){
setTo(src);
}
IntSet& IntSet::operator=(const IntSet& src) {
Attribute::operator=(src);
if(this->size != src.size){
delete[] value;
value = 0;
this->size = src.size;
if(size > 0){
value = new int[size];
}
}
if(size > 0){
memcpy((char*)value, src.value,size*sizeof(int));
}
return *this;
}
IntSet& IntSet::operator=(IntSet&& src) {
Attribute::operator=(src);
delete[] value;
size = src.size;
value = src.value;
src.size = 0;
src.value = 0;
return *this;
}
int IntSet::Compare(const IntSet& arg) const {
if(!IsDefined()){
return arg.IsDefined()?-1:0;
}
if(!arg.IsDefined()){
return 1;
}
if(size != arg.size){
return size < arg.size ? -1 : 1;
}
for(size_t i=0;i<size;i++){
if(value[i] < arg.value[i]) return -1;
if(value[i] > arg.value[i]) return 1;
}
return 0;
}
size_t IntSet::HashValue() const {
if(!IsDefined() ) return 0;
if(value==nullptr) return 42;
unsigned int step = size / 5;
if(step<1) step = 1;
size_t pos = 0;
size_t res = 0;
while(pos < size){
res += value[pos];
pos += step;
}
return res;
}
Word IntSet::In(const ListExpr typeInfo, const ListExpr le1,
const int errorPos, ListExpr& errorInfo, bool& correct) {
ListExpr le = le1;
Word res((void*)0);
if(listutils::isSymbolUndefined(le)){
res.addr = new IntSet(false);
correct = true;
return res;
}
if(nl->AtomType(le) != NoAtom){
correct = false;
return res;
}
std::set<int> tmp;
while(!nl->IsEmpty(le)){
ListExpr f = nl->First(le);
le = nl->Rest(le);
if(nl->AtomType(f)!=IntType){
correct = false;
return res;
}
tmp.insert(nl->IntValue(f));
}
IntSet* r = new IntSet(tmp);
res.addr = r;
correct = true;
return res;
}
ListExpr IntSet::Out(const ListExpr typeInfo, Word value) {
IntSet* is = (IntSet*) value.addr;
if(!is->IsDefined()){
return listutils::getUndefined();
}
if(is->size == 0){
return nl->TheEmptyList();
}
ListExpr res = nl->OneElemList( nl->IntAtom(is->value[0]));
ListExpr last = res;
for(unsigned int i=1;i<is->size;i++){
last = nl->Append(last, nl->IntAtom(is->value[i]));
}
return res;
}
bool IntSet::Open( SmiRecord& valueRecord, size_t& offset,
const ListExpr typeInfo, Word& value){
bool def;
if(!valueRecord.Read(&def, sizeof(bool), offset)){
return false;
}
offset += sizeof(bool);
if(!def){
value.addr = new IntSet(false);
return true;
}
size_t size;
if(!valueRecord.Read(&size, sizeof(size_t), offset)){
return false;
}
offset+=sizeof(size_t);
if(size==0){
value.addr = new IntSet(0,0);
return true;
}
int* v = new int[size];
if(!valueRecord.Read(v,size*sizeof(int),offset)){
return false;
}
value.addr = new IntSet(size,v);
return true;
}
bool IntSet::Save(SmiRecord& valueRecord, size_t& offset,
const ListExpr typeInfo, Word& value) {
IntSet* is = (IntSet*) value.addr;
bool def = is->IsDefined();
if(!valueRecord.Write(&def, sizeof(bool), offset)){
return false;
}
offset += sizeof(bool);
if(!def){
return true;
}
size_t size = is->size;
if(!valueRecord.Write(&size, sizeof(size_t), offset)){
return false;
}
offset += sizeof(size_t);
if(is->size>0){
if(!valueRecord.Write(is->value, sizeof(int) * is->size, offset)){
return false;
}
offset += sizeof(int) * is->size;
}
return true;
}
std::ostream& IntSet::Print( std::ostream& os ) const {
if(!IsDefined()){
os << "undefined";
return os;
}
os << "{";
for(size_t i=0;i<size;i++){
if(i>0) os << ", ";
os << value[i];
}
os << "}";
return os;
}
void IntSet::Rebuild(char* buffer, size_t sz) {
if(value!=nullptr){
delete[] value;
value = nullptr;
}
size = 0;
bool def;
size_t offset = 0;
memcpy(&def,buffer + offset, sizeof(bool));
offset += sizeof(bool);
if(!def){
SetDefined(false);
return;
}
SetDefined(true);
memcpy(&size, buffer+offset, sizeof(size_t));
offset += sizeof(size_t);
if(size > 0){
value = new int[size];
memcpy(value, buffer+offset, size * sizeof(int));
offset += size * sizeof(int);
}
}
void IntSet::setTo(const std::set<int>& src){
clear();
SetDefined(true);
if(src.size()>0){
size = src.size();
value = new int[size];
auto it = src.begin();
size_t pos = 0;
while(it!=src.end()) {
value[pos] = *it;
it++;
pos++;
}
}
}
void IntSet::setTo(const std::vector<int>& src) {
clear();
SetDefined(true);
if(src.size()>0){
size = src.size();
value = new int[size];
auto it = src.begin();
size_t pos = 0;
while(it!=src.end()) {
value[pos] = *it;
it++;
pos++;
}
}
}
IntSet IntSet::add(const IntSet& is) const{
if(!IsDefined() || !is.IsDefined()){
IntSet res(false);
return res;
}
std::vector<int> v;
size_t p1 = 0;
size_t p2 = 0;
while( p1 < size && p2 < is.size){
if(value[p1] < is.value[p2]){
v.push_back(value[p1]);
p1++;
} else if(value[p1] > is.value[p2]){
v.push_back(is.value[p2]);
p2++;
} else {
v.push_back(value[p1]);
p1++;
p2++;
}
}
while( p1 < size){
v.push_back(value[p1]);
p1++;
}
while( p2 < is.size){
v.push_back(is.value[p2]);
p2++;
}
IntSet res(true);
res.setTo(v);
return res;
}
IntSet IntSet::minus(const IntSet& is) const{
if(!IsDefined() || !is.IsDefined()){
IntSet res(false);
return res;
}
std::vector<int> v;
size_t p1 = 0;
size_t p2 = 0;
while( p1 < size && p2 < is.size){
if(value[p1] < is.value[p2]){
v.push_back(value[p1]);
p1++;
} else if(value[p1] > is.value[p2]){
p2++;
} else {
p1++;
p2++;
}
}
while( p1 < size){
v.push_back(value[p1]);
p1++;
}
IntSet res(true);
res.setTo(v);
return res;
}
IntSet IntSet::sdiff(const IntSet& is) const{
if(!IsDefined() || !is.IsDefined()){
IntSet res(false);
return res;
}
std::vector<int> v;
size_t p1 = 0;
size_t p2 = 0;
while( p1 < size && p2 < is.size){
if(value[p1] < is.value[p2]){
v.push_back(value[p1]);
p1++;
} else if(value[p1] > is.value[p2]){
v.push_back(is.value[p2]);
p2++;
} else {
p1++;
p2++;
}
}
while( p1 < size){
v.push_back(value[p1]);
p1++;
}
while( p2 < is.size){
v.push_back(is.value[p2]);
p2++;
}
IntSet res(true);
res.setTo(v);
return res;
}
IntSet IntSet::intersection(const IntSet& is) const {
if(!IsDefined() || !is.IsDefined()){
IntSet res(false);
return res;
}
std::vector<int> v;
size_t p1 = 0;
size_t p2 = 0;
while( p1 < size && p2 < is.size){
if(value[p1] < is.value[p2]){
p1++;
} else if(value[p1] > is.value[p2]){
p2++;
} else {
v.push_back(value[p1]);
p1++;
p2++;
}
}
IntSet res(true);
res.setTo(v);
return res;
}
bool IntSet::contains( const int i) const {
if(!IsDefined() || size==0){
return false;
}
int min = 0;
int max = size -1;
while(max > min){
int mid = (max + min) / 2;
int mv = value[mid];
if(mv == i){
return true;
}
if(mv < i){
min = mid + 1;
} else {
max = mid-1;
}
}
return value[min] == i;
}
bool IntSet::minCommon(const IntSet& is, int& result) const{
result = 0;
if(!IsDefined() || !is.IsDefined()){
return false;
}
size_t p1 = 0;
size_t p2 = 0;
while( p1 < size && p2 < is.size){
if(value[p1] < is.value[p2]){
p1++;
} else if(value[p1] > is.value[p2]){
p2++;
} else {
result = value[p1];
return true;
}
}
return false;
}
} // end of namespace
std::ostream& operator<<(std::ostream& out, const collection::IntSet& is){
return is.Print(out);
}