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

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

static char rcsid[] = "$Id: LazyPS.c,v 1.10 1994/07/25 16:58:52 thoth Exp $";

// 
// $Log: LazyPS.c,v $

#include <stdlib.h>

#include "OpTable.h"

/* resize the square table to have newcount*newcount entries,
   copy the function pointers into the new table,
   replace the old table.
*/

template <class A, class B, class C>
void IA_BinaryOperationsTable<A,B,C>::
resize_table(int newcount)
{
    function *newtable;

    newtable = new function [ newcount*newcount ];

    int	row, col;
    for (row=0; row<newcount && row<num_types(); row++) {
	for (col=0; col<newcount && col<num_types(); col++) {
	    newtable[ row*newcount + col ] = table[row*num_types() + col];
	}
	for ( ; col<newcount; col++)
	    newtable[ row*newcount + col ] = 0;
    }
    for ( ; row<newcount; row++) {
	for (col=0 ; col<newcount; col++)
	    newtable[ row*newcount + col ] = 0;
    }

    delete[] table;

    table = newtable;
}

template <class A, class B, class C>
int IA_BinaryOperationsTable<A,B,C>::
lookup_maybe_add(IA::Type t)
{
    if (t==0) return 0;

    for (int i=0; i<known_types.len(); i++) {
	if (t==known_types[i])
	    return i+1;
    }

    resize_table(i+2);
    known_types[i] = t;
    return i+1;
}

template <class A, class B, class C>
int IA_BinaryOperationsTable<A,B,C>::
lookup(IA::Type t) const
{
    for (int i=0; i<known_types.len(); i++) {
	if (t==known_types[i])
	    return i+1;
    }
    return 0;
}

template <class A, class B, class C>
IA_BinaryOperationsTable<A,B,C>::function &IA_BinaryOperationsTable<A,B,C>::
access_table(int row, int col)
{
    return table[row*num_types() + col];
}

template <class A, class B, class C>
IA_BinaryOperationsTable<A,B,C>::function IA_BinaryOperationsTable<A,B,C>::
access_table(int row, int col) const
{
    return table[row*num_types() + col];
}

//
//
//

template <class A, class B, class C>
void IA_BinaryOperationsTable<A,B,C>::
add_operation(IA::Type a, IA::Type b, function f)
{
    int	aidx = lookup_maybe_add(a);
    int	bidx = lookup_maybe_add(b);
    access_table(aidx, bidx) = f;
}

template <class A, class B, class C>
IA_BinaryOperationsTable<A,B,C>::function
IA_BinaryOperationsTable<A,B,C>::
lookup_operation(IA::Type a, IA::Type b) const
{
    int	aidx = lookup(a);
    int	bidx = lookup(b);

    function	f;

    f = access_table(aidx, bidx);
    if (f) return f;

    f = access_table(aidx,0);
    if (f) return f;

    f = access_table(0,bidx);
    if (f) return f;

    return access_table(0,0);
}

//
//
//


template <class A, class B>
void IA_UnaryOperationsTable<A,B>::
resize_table(int newcount)
{
    function *newtable;

    newtable = new function [ newcount ];

    int	col;
    for (col=0; col<newcount && col<num_types(); col++) {
	newtable[ col ] = table[col];
    }
    for ( ; col<newcount; col++)
	newtable[ col ] = 0;

    delete[] table;

    table = newtable;
}

template <class A, class B>
int IA_UnaryOperationsTable<A,B>::
lookup_maybe_add(IA::Type t)
{
    if (t==0) return 0;

    for (int i=0; i<known_types.len(); i++) {
	if (t==known_types[i])
	    return i+1;
    }

    resize_table(i+2);
    known_types[i] = t;
    return i+1;
}

template <class A, class B>
int IA_UnaryOperationsTable<A,B>::
lookup(IA::Type t) const
{
    for (int i=0; i<known_types.len(); i++) {
	if (t==known_types[i])
	    return i+1;
    }
    return 0;
}

template <class A, class B>
IA_UnaryOperationsTable<A,B>::function &IA_UnaryOperationsTable<A,B>::
access_table(int col)
{
    return table[col];
}

template <class A, class B>
IA_UnaryOperationsTable<A,B>::function IA_UnaryOperationsTable<A,B>::
access_table(int col) const
{
    return table[col];
}

//
//
//

template <class A, class B>
void IA_UnaryOperationsTable<A,B>::
add_operation(IA::Type a, function f)
{
    int	aidx = lookup_maybe_add(a);
    access_table(aidx) = f;
}

template <class A, class B>
IA_UnaryOperationsTable<A,B>::function
IA_UnaryOperationsTable<A,B>::
lookup_operation(IA::Type a) const
{
    int	aidx = lookup(a);

    function	f;

    f = access_table(aidx);
    if (f) return f;

    return access_table(0);
}
