// $Id: vectorx.h,v 1.23 2018/01/03 21:33:03 mkkuhner Exp $

/*
Copyright 2002-2005 Mary K. Kuhner, Peter Beerli, and Joseph Felsenstein

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

/* Authors: Peter Beerli, Mary Kuhner, Jon Yamato and Joseph Felsenstein */


// Vector utilities
//
// VECTOR SETTERS
// - Sets n-dimensional vector to an initial value,
//   assumes that the vector has allocated elements
// VECTOR CREATION
// - Creates 1-D and 2-D vectors with an initial value
// VECTOR TYPES
// - Typedefs for n-dimensional vectors
// VECTOR MATH UTILITIES
// - vector = Log(vector) in save and unsave (sic!) versions of it.
// VECTOR TRANSMOGRIFIER
// - turn a 1D into a 2D vector (must be square!)

#ifndef VECTORX_H
#define VECTORX_H

#include <vector>
#include <algorithm>
#include <string>
#include "constants.h"
#include "definitions.h"
#include "ui_id.h"

using std::vector;
using std::string;

// This should be in mathx.h except that mathx.h includes
// this file, and we use this below so we can't
long LongSquareRootOfLong(long x);

class Force;

// VECTOR CREATION ------------------------------------------------------
//    a set of vector of vectors setters:
//    there is no error checking, these will *return* a new vector and

template <class T>
vector <T>  CreateVec1d(long n, T initial)
{
    vector<T> one(static_cast<typename vector<T>::size_type> (n),initial);
    return one;
}

template <class T>
vector < vector <T> > CreateVec2d(long n, unsigned long m, T initial)
{
    vector<T> one(static_cast<typename vector<T>::size_type> (m),initial);
    vector < vector <T> > two(n,one);
    return two;
}

// VECTOR DEFINITIONS ---------------------------------------------------
// Typedefs for commonly used multidimensional vectors
// WARNING:  Some version of g++ refuse to accept a 4+
// dimensional vector of vectors unless they have already, in
// compiling that source file, found a smaller vector.  To work
// around this bug it may be necessary to declare a dummy vector.

typedef vector<string>        StringVec1d;
typedef vector<StringVec1d>   StringVec2d;
typedef vector<StringVec2d>   StringVec3d;
typedef vector<StringVec3d>   StringVec4d;
typedef vector<StringVec4d>   StringVec5d;

typedef vector<double>        DoubleVec1d;
typedef vector<DoubleVec1d>   DoubleVec2d;
typedef vector<DoubleVec2d>   DoubleVec3d;
typedef vector<DoubleVec3d>   DoubleVec4d;
typedef vector<DoubleVec4d>   DoubleVec5d;

typedef vector<Force*>        ForceVec;

typedef vector<long>          LongVec1d;
typedef vector<LongVec1d>     LongVec2d;
typedef vector<LongVec2d>     LongVec3d;
typedef vector<LongVec3d>     LongVec4d;
typedef vector<LongVec4d>     LongVec5d;

typedef vector<unsigned long> ULongVec1d; //like the tea.
typedef vector<ULongVec1d>    ULongVec2d;
typedef vector<ULongVec2d>    ULongVec3d;

typedef vector<int>           IntVec1d;
typedef vector<IntVec1d>      IntVec2d;
typedef vector<IntVec2d>      IntVec3d;
typedef vector<IntVec3d>      IntVec4d;
typedef vector<IntVec4d>      IntVec5d;

typedef vector<model_type>          ModelTypeVec1d;

typedef vector<method_type>         MethodTypeVec1d;
typedef vector<MethodTypeVec1d>     MethodTypeVec2d;

typedef vector<proftype>            ProftypeVec1d;
typedef vector<force_type>          ForceTypeVec1d;

typedef vector<UIId>                UIIdVec1d;
typedef vector<UIIdVec1d>           UIIdVec2d;

typedef vector<data_source>         DataSourceVec1d;

//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------

// VectorAppend() puts "vec2" onto the end of "vec1"
template <class T>
vector<T> VectorAppend(const vector<T>& vec1, const vector<T>& vec2)
{
    vector<T> vec = vec1;
    typename vector<T>::const_iterator vit;
    for(vit = vec2.begin(); vit != vec2.end(); ++vit)
        vec.push_back(*vit);

    return(vec);
} // VectorAppend

//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------

// VECTOR MATH UTILITIES ------------------------------------------------------
//
void LogVec0(const vector<double> &in, vector<double> &out);

//------------------------------------------------------------------------------------
// This function takes a linear vector and turns it into
// a square two-dimensional vector.  It will throw an exception
// if the size of the linear vector is not a perfect square.
// It assumes that diagonal entries ARE PRESENT.
//
// It is templated on the type contained in the vector.

template<class T>
vector<vector<T> > SquareOffVector(const vector<T>& src)
{
    long dim = LongSquareRootOfLong(src.size());

    // convert linear matrix into square matrix

    vector<T> vec1D;
    vector<vector<T> > vec2D;
    typename vector<T>::const_iterator it = src.begin();

    vec1D.reserve(dim);                   // for speed
    vec2D.reserve(dim);

    long i;
    long j;

    for (i = 0; i < dim; i++)
    {
        for (j = 0; j < dim; ++j, ++it)
        {
            vec1D.push_back(*it);
        }

        vec2D.push_back(vec1D);
        vec1D.clear();
    }

    return vec2D;

} // SquareOffVector

//------------------------------------------------------------------------------------
// vector comparison with scalar
//
template < class T >
bool vec_leq(vector < T > v, T comparison)
{
    typename vector< T > :: iterator vecit;
    for(vecit = v.begin(); vecit != v.end(); vecit++)
    {
        if(*vecit > comparison)
            return false;
    }
    return true;
}

template <class T>
bool vec_greater(vector < T > v, T comparison)
{
    typename vector< T > :: iterator vecit;
    for(vecit = v.begin(); vecit != v.end(); vecit++)
    {
        if(*vecit <= comparison)
            return false;
    }
    return true;
}

//------------------------------------------------------------------------------------
// convenience wrapper for find
//

template < class T >
bool Contains(const std::vector<T>& collection, const T& item)
{
    typename std::vector<T>::const_iterator it =
        std::find(collection.begin(), collection.end(), item);
    return (it != collection.end());
}


#endif // VECTORX_H

//____________________________________________________________________________________
