/*****************************************************************************
 *
 * $Id$
 *
 * Copyright (C) 2009 - 2012  Richard Hacker <lerich@gmx.net>
 *                            Florian Pose <fp@igh-essen.com>
 *
 * This file is part of the PdCom library.
 *
 * The PdCom library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * The PdCom library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with the PdCom Library. If not, see <http://www.gnu.org/licenses/>.
 *
 ****************************************************************************/

#include "pdcom/Data.h"

#define DEBUG 0

#if DEBUG
#include <iostream>
namespace {
    using std::cout;
    using std::cerr;
    using std::endl;
}
#endif

using namespace PdCom;

////////////////////////////////////////////////////////////////////////////
//  class Data::Dimension
////////////////////////////////////////////////////////////////////////////

/****************************************************************************/
Data::Dimension::Dimension(
        const std::allocator<size_t>& a) :
    vector<size_t>(a)
{
}

/****************************************************************************/
Data::Dimension::Dimension ( size_t n, const size_t& value,
        const std::allocator<size_t>& a) :
    vector<size_t>(n, value, a)
{
}

/****************************************************************************/
Data::Dimension::Dimension ( const vector<size_t>::iterator& first,
        const vector<size_t>::iterator& last,
        const std::allocator<size_t>& a) :
    vector<size_t>(first, last, a)
{
}

/****************************************************************************/
Data::Dimension::Dimension ( const vector<size_t>& other):
    vector<size_t>(other)
{
}

/****************************************************************************/
size_t Data::Dimension::getElementCount() const
{
    size_t n = 1;
    for( vector<size_t>::const_iterator it = begin();
            it != end(); it++) {
        n *= *it;
    }
    return n;
}

/****************************************************************************/
unsigned int Data::Dimension::getOffset(const Dimension* element) const
{
    if (!element)
        return 0;

    unsigned int n = (*element)[0];
    unsigned int elementSize = element->size();

    for (unsigned int i = 1; i < size(); i++) {
        n = n * (*this)[i] + i < elementSize ? (*element)[i] : 0;
    }
    // Note: this class method has optimization potential. dimX could
    // be cached so it doesn't need to be calculated every time

    return n;
}
