// Copyright (C) 1996 DIMACS Center, Rutgers, The State University of New Jersey
// Author(s): Jonathan Berry

// This software is copyrighted by the DIMACS Center at Rutgers, The State
// University of New Jersey.  IT IS PROVIDED AS IS, AND THE AUTHORS, DIMACS, AND
// RUTGERS, THE STATE UNIVERSITY OF NEW JERSEY  DISCLAIM
// ALL LIABILITY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
// DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

// THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
// IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
// NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
// MODIFICATIONS.

// The authors hereby grant permission to use, copy, modify, distribute,
// and license this software and its documentation for any purpose, provided
// that existing copyright notices are retained in all copies and that this
// notice is included verbatim in any distributions. No written agreement,
// license, or royalty fee is required for any of the authorized uses.
// Modifications to this software may be copyrighted by their authors
// and need not follow the licensing terms described here, provided that
// the new terms are clearly indicated on the first page of each file where
// they apply.

// Last File Update: 31-Jul-1996
// 

#include <stk.h>
#include <iostream.h>
#include <strstream.h>
#include <LINK/stkWrapper/LINK_STk.h>
#include <LINK/basic/SetFuncs.h>
#include <LINK/stkWrapper/CollectionWrapper.h>


template <class T> 
PRIMITIVE 
SetFuncsWrapper<T>::cartesianProduct(SCM base_set1, SCM base_set2)
{
	int i;
	SCM ns;
	Collection<T>* cp1, *cp2;
	Collection<Sequence<T> >* cpp;

	int &Set_Sequence_Type	= Wrapper<Set<Sequence<T> > >::type;
	char*Set_Sequence_Name	= Wrapper<Set<Sequence<T> > >::name;
	
	if (!CollectionWrapper<T>::isCollection(base_set1)) 
		Err("cartesian-product: bad arg 1 (set expected)", base_set1);
	if (!CollectionWrapper<T>::isCollection(base_set2)) 
		Err("cartesian-product: bad arg 2 (set expected)", base_set2);
	
	cp1 = CollectionWrapper<T>::getCollection(base_set1);
	cp2 = CollectionWrapper<T>::getCollection(base_set2);
	if (!cp1 || !cp2)
		Err("cartesian-product: bad collection", NIL);
	Set<T> s1 = *cp1;
	Set<T> s2 = *cp2;
	Set<Sequence<T> > ss = SetFuncs<T>::cartesianProduct(s1, s2);
	cpp = new Set<Sequence<T> >(ss);
	ns = STk_make_CXXwrapper(Set_Sequence_Type,Set_Sequence_Name,
					(void*)cpp,LINK_DYNAMIC);
	return ns;
}

template <class T> 
PRIMITIVE 
SetFuncsWrapper<T>::choose(SCM base_set, SCM k)
{
	int i;
	SCM ns;
	Collection<T>* cp;
	Collection<Set<T> >* cpp;

	int &Set_Set_Type	= Wrapper<Set<Set<T> > >::type;
	char*Set_Set_Name	= Wrapper<Set<Set<T> > >::name;
	
	if (!CollectionWrapper<T>::isCollection(base_set)) 
		Err("choose: bad arg 1 (set expected)", base_set);
	if (!INTEGERP(k)) 
		Err("choose: bad arg 2 (integer expected)", k);
	i = INTEGER(k);
	
	cp = CollectionWrapper<T>::getCollection(base_set);
	if (!cp)
		Err("choose: bad collection", NIL);
	Set<T> s = *cp;
	Set<Set<T> > ss = SetFuncs<T>::choose(s, i);
	cpp = new Set<Set<T> >(ss);
	ns = STk_make_CXXwrapper(Set_Set_Type,Set_Set_Name,
					(void*)cpp,LINK_DYNAMIC);
	return ns;
}

template <class T> 
PRIMITIVE 
SetFuncsWrapper<T>::powerSet(SCM base_set)
{
	SCM ns;
	Collection<T>* cp;
	Collection<Set<T> >* cpp;

	int &Set_Set_Type	= Wrapper<Set<Set<T> > >::type;
	char*Set_Set_Name	= Wrapper<Set<Set<T> > >::name;
	
	if (!CollectionWrapper<T>::isCollection(base_set)) 
		Err("power-set: bad arg 1 (set expected)", base_set);
	
	cp = CollectionWrapper<T>::getCollection(base_set);
	if (!cp)
		Err("power-set: bad collection", NIL);
	Set<T> s = *cp;
	Set<Set<T> > ss = SetFuncs<T>::powerSet(s);
	cpp = new Set<Set<T> >(ss);
	ns = STk_make_CXXwrapper(Set_Set_Type,Set_Set_Name,
					(void*)cpp,LINK_DYNAMIC);
	return ns;
}

template <class T> 
PRIMITIVE 
SetFuncsWrapper<T>::permutations(SCM base_set)
{
	SCM ns;
	Collection<T>* cp;
	Collection<Sequence<T> >* cpp;

	int &Set_Sequence_Type	= Wrapper<Set<Sequence<T> > >::type;
	char*Set_Sequence_Name	= Wrapper<Set<Sequence<T> > >::name;
	
	if (!CollectionWrapper<T>::isCollection(base_set)) 
		Err("choose: bad arg 1 (set expected)", base_set);
	
	cp = CollectionWrapper<T>::getCollection(base_set);
	if (!cp)
		Err("permutations: bad collection", NIL);
	Set<T> s = *cp;
	Set<Sequence<T> > ss = SetFuncs<T>::permutations(s);
	cpp = new Set<Sequence<T> >(ss);
	ns = STk_make_CXXwrapper(Set_Sequence_Type,Set_Sequence_Name,
					(void*)cpp,LINK_DYNAMIC);
	return ns;
}

template <class T> 
PRIMITIVE 
SetFuncsWrapper<T>::rank(SCM seq)
{
	SCM ns;
	int r;
	Collection<T>* cp;
	Collection<Sequence<T> >* cpp;

	if (!CollectionWrapper<T>::isCollection(seq)) 
		Err("choose: bad arg 1 (collection expected)", seq);
	
	cp = CollectionWrapper<T>::getCollection(seq);
	if (!cp)
		Err("permutations: bad collection", NIL);
	Sequence<T> s = *cp;
	r = SetFuncs<T>::rank(s);
	return STk_makeinteger(r);
}

template <class T> 
PRIMITIVE 
SetFuncsWrapper<T>::permutation(SCM base_set, SCM k)
{
	int i;
	SCM ns;
	Collection<T>* cp;
	Sequence<T> * cpp;

	int &sequence_type	= Wrapper<Sequence<T> >::type;
	char*sequence_name	= Wrapper<Sequence<T> >::name;
	
	if (!CollectionWrapper<T>::isCollection(base_set)) 
		Err("choose: bad arg 1 (set expected)", base_set);
	if (!INTEGERP(k)) 
		Err("choose: bad arg 2 (integer expected)", k);
	i = INTEGER(k);
	
	cp = CollectionWrapper<T>::getCollection(base_set);
	if (!cp)
		Err("choose: bad collection", NIL);
	Set<T> s = *cp;
	Sequence<T> ss = SetFuncs<T>::permutation(s, i);
	cpp = new Sequence<T>(ss);
	ns = STk_make_CXXwrapper(sequence_type,sequence_name,
					(void*)cpp,LINK_DYNAMIC);
	return ns;
}
