//
// LiDIA - a library for computational number theory
//   Copyright (c) 1994, 1995 by the LiDIA Group
//
// File        : p_vector.c
// Author      : Werner Backes (WB), Thorsten Lauer (TL)
// Last change : WB/TL, May 09 1996,
//                      initial version, previously
//                      class bigint_lattice_gensys/basis
//               WB/TL, Jul 27 1996,
//                      new template class p_vector, p_vector_SP initial version
//                      - p_vector
//                        -> template class used to work with pointers to
//                           a template datatype
//                      - p_vector_SP
//                        -> see above, user defined scalarproduct with
//                           pointer to function
//               WB/TL, Aug 06 1996, removed several bugs, specialized
//                                   versions of p_vector for bigint/bigfloat
//
//

#ifndef __p_vector_c__
#define __p_vector_c__

#ifdef NO_P_VECTOR_INLINE
#include <LiDIA/p_vector.h>
#else
#ifdef LIDIA_INLINE_PROBLEM
#include <LiDIA/p_vector.h>
#undef P_VECTOR_INLINE
#define P_VECTOR_INLINE
#endif
#endif

P_VECTOR_INLINE void p_vector<bigint>::assign(bigint* c, bigint* a)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    c[counter].assign(a[counter]);
}

P_VECTOR_INLINE void p_vector<bigint>::assign_zero(bigint* a)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    a[counter].assign_zero();
}

P_VECTOR_INLINE void p_vector<bigint>::add(bigint* c, bigint* a,  bigint* b)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    ::add(c[counter],a[counter],b[counter]);
}

P_VECTOR_INLINE void p_vector<bigint>::subtract(bigint* c, bigint* a,  bigint* b)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    ::subtract(c[counter],a[counter],b[counter]);
}

P_VECTOR_INLINE void p_vector<bigint>::scalmul(bigint* c, const bigint d, bigint* a)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    ::multiply(c[counter],d,a[counter]);
}

P_VECTOR_INLINE void p_vector<bigint>::scalsub(bigint* c, bigint* a, 
				      const bigint d, bigint* b)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    {
      ::multiply(tempT, d, b[counter]);
      ::subtract(c[counter], a[counter], tempT);
    }
}

P_VECTOR_INLINE void p_vector<bigint>::scalprod(bigint& res, bigint* a, bigint * b)
{
  res.assign_zero();
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    {
      ::multiply(tempT, a[counter], b[counter]);
      ::add(res, res, tempT);
    }
}

P_VECTOR_INLINE void p_vector<bigint>::swap(bigint*& a, bigint*& b)
{
  tempPT=a;
  a=b;
  b=tempPT;
}

P_VECTOR_INLINE void p_vector<bigfloat>::assign(bigfloat* c, bigfloat* a)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    c[counter].assign(a[counter]);
}

P_VECTOR_INLINE void p_vector<bigfloat>::assign_zero(bigfloat* a)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    a[counter].assign_zero();
}

P_VECTOR_INLINE void p_vector<bigfloat>::add(bigfloat* c, bigfloat* a,  bigfloat* b)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    ::add(c[counter],a[counter],b[counter]);
}

P_VECTOR_INLINE void p_vector<bigfloat>::subtract(bigfloat* c, bigfloat* a,  bigfloat* b)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    ::subtract(c[counter],a[counter],b[counter]);
}

P_VECTOR_INLINE void p_vector<bigfloat>::scalmul(bigfloat* c, const bigfloat d, 
					bigfloat* a)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    ::multiply(c[counter],d,a[counter]);
}

P_VECTOR_INLINE void p_vector<bigfloat>::scalsub(bigfloat* c, bigfloat* a, 
					const bigfloat d, bigfloat* b)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    {
      ::multiply(tempT, d, b[counter]);
      ::subtract(c[counter], a[counter], tempT);
    }
}

P_VECTOR_INLINE void p_vector<bigfloat>::scalprod(bigfloat& res, bigfloat* a, 
					 bigfloat * b)
{
  res.assign_zero();
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    {
      ::multiply(tempT, a[counter], b[counter]);
      ::add(res, res, tempT);
    }
}

P_VECTOR_INLINE void p_vector<bigfloat>::swap(bigfloat*& a, bigfloat*& b)
{
  tempPT=a;
  a=b;
  b=tempPT;
}

template <class T>
P_VECTOR_INLINE void p_vector<T>::assign(T* c, T* a)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    c[counter]=a[counter];
}

template <class T>
P_VECTOR_INLINE void p_vector<T>::assign_zero(T* a)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    a[counter]=0;
}

template <class T>
P_VECTOR_INLINE void p_vector<T>::add(T* c, T* a, T* b)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    c[counter]=a[counter]+b[counter];
}

template <class T>
P_VECTOR_INLINE void p_vector<T>::subtract(T* c, T* a,  T* b)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    c[counter]=a[counter]-b[counter];
}

template <class T>
P_VECTOR_INLINE void p_vector<T>::scalmul(T* c, const T d, T* a)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    c[counter]=d*a[counter];
}

template <class T>
P_VECTOR_INLINE void p_vector<T>::scalsub(T* c, T* a, const T d, T* b)
{
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    c[counter]=a[counter]-d*b[counter];
}

template <class T>
P_VECTOR_INLINE void p_vector<T>::scalprod(T& res, T* a, T * b)
{
  res=0;
  for (fcl(counter)=vectsize-1;counter>=0;counter--)
    res+=a[counter]*b[counter];
}

template <class T>
P_VECTOR_INLINE void p_vector<T>::swap(T*& a, T*& b)
{
  tempPT=a;
  a=b;
  b=tempPT;
}

#endif
