// Emacs: -*- C++ -*-

//
//	Copyright 1993, Center for Computer Vision and Visualization,
//	University of Florida.  All rights reserved.
//

static char copyright[] = "Copyright 1993, Center for Computer Vision and Visualization,\nUniversity of Florida.  All rights reserved.\n";

static char rcsid[] = "$Id: SetStructure.c,v 1.7 1993/05/26 16:57:50 thoth Exp $";

// 
// $Log: SetStructure.c,v $
// Revision 1.7  1993/05/26  16:57:50  thoth
// Copyright Notices
//
// Revision 1.6  92/12/16  14:48:19  thoth
// conversion to IA_ mostly complete
// 
// Revision 1.5  92/11/15  15:57:50  thoth
// expect a slight performance increase with preallocation.
// 
// Revision 1.4  92/11/11  12:17:14  thoth
// incremental optimization of SetStructures.
// 
// Revision 1.3  92/11/04  11:59:37  thoth
// stylistic improvements.
// 
// Revision 1.2  92/10/25  20:55:25  thoth
// made recursion termination constants have sensible names.
// 
// Revision 1.1  92/10/21  14:58:12  thoth
// Initial revision
// 
//

#include "SetStructure.h"

typedef IA_real_ss	real_ss;
typedef IA_ss_interval	ss_interval;
typedef IA_SetStructure	SetStructure;

static real_ss	alpha(1.0), beta(1.0), gamma(1.0);
const SetStructure SetStructure::FIRST_ONLY  (&alpha);
const SetStructure SetStructure::SECOND_ONLY (&beta);
const SetStructure SetStructure::BOTH   (&gamma);

void SetStructure::copy_on_write()
{
    if (!val) {
	val = new real_ss;
	return;
    }
    if (val->refcount<2)
	return;
    real_ss *temp=new real_ss(*val);
    val->refcount--;
    val = temp;
}

SetStructure::IA_SetStructure(real_ss *val_)
{
    val = val_;
    if (val)
	val->refcount++;
}

SetStructure::IA_SetStructure()
{
    val = 0;
}

SetStructure::IA_SetStructure(const SetStructure &ss)
{
    val = ss.val;
    if (val)
	val->refcount++;
}

SetStructure::~IA_SetStructure()
{
    if (val)
	if (0>=--val->refcount)
	    delete val;
    val=0;
}

SetStructure& SetStructure::operator=(const SetStructure& rhs)
{
    if (rhs.val)
	rhs.val->refcount++;
    if (val) {
	if (0 >= --val->refcount)
	    delete val;
    }
    val = rhs.val;
    return *this;
}

void SetStructure::add_interval(unsigned count, SetStructure sub)
{
    if (sub.val==0 || sub.val->ivls.len()==0)
	// if the substructure is empty, why add it?
	return;

    copy_on_write();

    if (val->ivls.len()>0 && val->ivls.last().substructure == sub) {
	val->ivls.last().count += count;
	return;
    }

    ss_interval 	&ivl = val->ivls.after_last();

    if (sub.val->ivls.len()==1) {
	ivl.count = count * sub.val->ivls[0].count;
	ivl.substructure = sub.val->ivls[0].substructure;
    } else {
	ivl.count = count;
	ivl.substructure = sub;
    }
}

ss_interval SetStructure::retrieve_interval(unsigned idx) const
{
    if (val)
	return val->ivls[idx];
    else
	return ss_interval();
}

unsigned SetStructure::nintervals() const
{
    if (val)
	return val->ivls.len();
    else
	return 0;
}

void SetStructure::ensure_space(unsigned howmuch)
{
    copy_on_write();

    unsigned	len=val->ivls.len();
    val->ivls.lengthen(len+howmuch);
    val->ivls.shorten(len);
}
