Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> работа с трехмерными массивами 
:(
    Опции темы
RedDigger
Дата 30.9.2010, 00:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 24.9.2010
Где: Москва

Репутация: 1
Всего: 1



Цитата(JackYF @ 29.9.2010,  23:09)
Цитата(RedDigger @  25.9.2010,  12:03 Найти цитируемый пост)
Но при этом не учитывается что вектор занимает в памяти намного больше места нежели обычный массив.

Откуда информация?

Программа номер раз
Код

#include "boost/multi_array.hpp"
#include <iostream>

using namespace std;

int main(int argc, char ** argv) {
         typedef boost::multi_array<double, 3> array_type;
         array_type A(boost::extents[3][4][2]);
         printf("Sizeof boost::multi_array is %d\n", sizeof(A));
         return 0;
}



вывод - 
Код

Sizeof boost::multi_array is 80


программа номер два..
Код

#include "myarray.h"
#include <iostream>
using namespace std;

int main() {
        MyArray *array = new MyArray(3,3,3);
        cout << "Size of MyArray is " << sizeof(*array) << endl;
}


вывод - 
Код

Size of MyArray is 16



PM MAIL Skype   Вверх
Master01
Дата 30.9.2010, 13:33 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 22.8.2007

Репутация: 2
Всего: 2




Вы не совсем правильно понимаете эти результаты. Контейнер  будет занимать всегда на N  байт больше и это не зависит от количества элементов. Например, если память мне не изменяет, std::vector даже пустой (не содержащий полезных данных) занимает  где-то 20 байт.

т.о. если говорить, к примеру, о массиве int из 1024 элементов, требующих для хранения (предполагаем что int = 4 байта) 4 Кб, то эти 20 байт уже не кажутся таким кащунственным разбазареванием ресурсов.

А лепить что-то своё, ради выйгрыша в 20 байт весьма сомнительно ...

а вот политика выделения памяти, которой следует тот или иной контейнер - это действительно то, на что слежует обратить внимание, если нужно что-то оптимизировать.
PM MAIL   Вверх
RedDigger
Дата 30.9.2010, 13:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 24.9.2010
Где: Москва

Репутация: 1
Всего: 1



Не учел... Спасибо за разъеснение.   
PM MAIL Skype   Вверх
Леопольд
Дата 30.9.2010, 16:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(RedDigger @  25.9.2010,  13:03 Найти цитируемый пост)
Но при этом не учитывается что вектор занимает в памяти намного больше места нежели обычный массив.
Проблемма не в этом а в копировании векторов, которые являются элементами вектора. Делается глубокое копирование. Т.е. swap двух векторов один/два раза выделяется память под новый массив данных и трижды делается глубокая копия. IMHO это несколько расточительно.

Тут вроде-бы в помощь shared_ptr, но для того что-бы достучаться до элемента, придётся делать как-то так:
Код
typedef boost::shared_ptr<std::vector<int> > dim1_t;
typedef boost::shared_ptr<std::vector<dim1_t> > dim2_t;

std::vector<dim2_t> array;

array.push_back(dim2_t(new std::vector<dim1_t>));
array.back()->push_back(dim1_t(new std::vector<int>));
array.back()->back()->push_back(123);
std::cout<<(*(*array[0])[0])[0]<<std::endl;
// и т.д. и т.п.

Лично мне такой вариант не очень...

Это сообщение отредактировал(а) Леопольд - 30.9.2010, 16:43


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
JackYF
Дата 30.9.2010, 20:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Цитата(Леопольд @  30.9.2010,  15:29 Найти цитируемый пост)
трижды делается глубокая копия

Что-то я не понял, почему трижды. При глубоком копировании вектора векторов векторов векторов ... любой степени вложенности всё копируется единожды. По крайней мере, если вектор == std::vector. Но так должно быть и у любого другого вменяемого вектора.


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Леопольд
Дата 2.10.2010, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(JackYF @  30.9.2010,  20:50 Найти цитируемый пост)
Что-то я не понял, почему трижды.
Я говорил про swap, который повсеместно используется в STL. Он создаёт временную копию.

Это сообщение отредактировал(а) Леопольд - 2.10.2010, 10:13


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
mes
Дата 2.10.2010, 10:20 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Леопольд @  30.9.2010,  15:29 Найти цитируемый пост)
Т.е. swap двух векторов 


Цитата(Леопольд @  2.10.2010,  09:03 Найти цитируемый пост)
Я говорил про swap, который повсеместно используется в STL. Он создаёт временную копию.

я Вас правильно понял, что swap одного вектора в другой медленее чем просто копия ?





--------------------
PM MAIL WWW   Вверх
ElKa
Дата 2.10.2010, 17:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 300
Регистрация: 1.2.2006

Репутация: нет
Всего: 4



RedDigger

а как передавать такие массивы объектам других классов? 

мне нужно создавать объекты, которые содержат по два трехмерных массива 
в общем конструктор должен быть такой

Код

WCl::WCl(MyArray  p, MyArray n, int id)
{
    _p = p;
    _n = n;
    _id = id;
    }


и операторы наверное же тоже нужны

myarray.h
Код

        MyArray &operator=(MyArray &right);
        int &operator!=(MyArray &right);
        int &operator [](int i);

myarray.cxx
Код

MyArray &MyArray::operator=(MyArray &right){
        if(&right != this)
        {
            delete [] a_;
            _size1 = right.getSize1();
            _size2 = right.getSize2();
            _size3 = right.getSize3();
            a_ = new T[_size1*_size2*_size3];
            assert(a_ != 0);

            for(int i=0; i<_size1; ++i)
                for(int j=0; j<_size2; ++j)
                    for(int k=0; k<_size3; ++k)
                        a_[i*j*k] = &right[i*j*k];
        }
        return *this;
    }

int &MyArray::operator!=(MyArray &right)
    {
        if(_size1 != right.getSize1() || _size2 != right.getSize2() || _size3 != right.getSize3())
            return 1;

        for(int i=0; i<_size1; ++i)
            for(int j=0; j<_size2; ++j)
                for(int k=0; k<_size3; ++k)
                    if(a_[i][j][k] != right[i][j][k]) return 1;

        return 0;
    }

int &MyArray::operator [](int i)
    {
       return a_[i];
    }





Это сообщение отредактировал(а) ElKa - 2.10.2010, 17:58
PM   Вверх
JackYF
Дата 2.10.2010, 21:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Цитата(Леопольд @  2.10.2010,  09:03 Найти цитируемый пост)
Я говорил про swap, который повсеместно используется в STL. Он создаёт временную копию.

Я сомневаюсь, что swap двух векторов делает временную копию. Проверяли?


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
RedDigger
Дата 2.10.2010, 21:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 24.9.2010
Где: Москва

Репутация: 1
Всего: 1



Цитата(ElKa @ 2.10.2010,  17:25)
RedDigger

а как передавать такие массивы объектам других классов? 

мне нужно создавать объекты, которые содержат по два трехмерных массива 
в общем конструктор должен быть такой

Код

WCl::WCl(MyArray  p, MyArray n, int id)
{
    _p = p;
    _n = n;
    _id = id;
    }


и операторы наверное же тоже нужны

myarray.h
Код

        MyArray &operator=(MyArray &right);
        int &operator!=(MyArray &right);
        int &operator [](int i);

myarray.cxx
Код

MyArray &MyArray::operator=(MyArray &right){
        if(&right != this)
        {
            delete [] a_;
            _size1 = right.getSize1();
            _size2 = right.getSize2();
            _size3 = right.getSize3();
            a_ = new T[_size1*_size2*_size3];
            assert(a_ != 0);

            for(int i=0; i<_size1; ++i)
                for(int j=0; j<_size2; ++j)
                    for(int k=0; k<_size3; ++k)
                        a_[i*j*k] = &right[i*j*k];
        }
        return *this;
    }

int &MyArray::operator!=(MyArray &right)
    {
        if(_size1 != right.getSize1() || _size2 != right.getSize2() || _size3 != right.getSize3())
            return 1;

        for(int i=0; i<_size1; ++i)
            for(int j=0; j<_size2; ++j)
                for(int k=0; k<_size3; ++k)
                    if(a_[i][j][k] != right[i][j][k]) return 1;

        return 0;
    }

int &MyArray::operator [](int i)
    {
       return a_[i];
    }


Лучше всего передовать их по ссылке. В данном случае стек вызовов не переполняется лишними объектами. А внутри класса куда тебе надо завести данные создаешь член класса типа MyArray * (допустим)_b. 

Но с операторами ты немного намудрила. впринципе могу помочь.. 
Мои координаты - 
Skype: sl.spell
Mail: pn.spell{at}gmail.com
PM MAIL Skype   Вверх
Леопольд
Дата 3.10.2010, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(JackYF @  2.10.2010,  21:08 Найти цитируемый пост)
Я сомневаюсь, что swap двух векторов делает временную копию. Проверяли? 
Неа, не проверял, а зря. Вызывается векторный swap...


Это сообщение отредактировал(а) Леопольд - 3.10.2010, 17:01


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
mes
Дата 3.10.2010, 17:33 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Леопольд @  3.10.2010,  16:01 Найти цитируемый пост)
 а зря

smile
Цитата

23.2.4.4 vector specialized algorithms
   template <class T, class Allocator>
   void swap(vector<T,Allocator>& x, vector<T,Allocator>& y);
 Effects:
   x.swap(y);


Это сообщение отредактировал(а) mes - 3.10.2010, 17:34


--------------------
PM MAIL WWW   Вверх
ElKa
Дата 5.10.2010, 22:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 300
Регистрация: 1.2.2006

Репутация: нет
Всего: 4



посмотрите пожалуйста код
почему то не те элементы вызываются и зависает ехе
массивы 3мерные и что-то я с этими указателями запуталась
и еще меня смущает operator [](int i), я его оставила таким же как для одномерных массивов, это правильно? 

array.h
Код

#ifndef ARRAY_H_
#define ARRAY_H_

class Array {
public:
    Array();
        Array(int, int, int);
        ~Array();
        int getSize1();
        int getSize2();
        int getSize3();
        bool setValue(int, int, int, float); 
        float getValue(int, int, int);
        Array &operator=(Array &right);
        int operator!=(Array &right);
        float** &operator[](int);

private:
        float *** a_;
        int _size1;
        int _size2;
        int _size3;
};

#endif


array.cxx
Код

#include "array.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;

Array::Array(){}

Array::Array(int size1, int size2, int size3) {
       int i,j,k;
       a_ = (float ***)malloc( size1 * sizeof(int));
       // **a_ = new float[size1];
        for(i = 0; i < size1; i++) {
            a_[i] = (float **) malloc( size2 * sizeof(int) );
         //*a_[i] = new float[size2];
                for(j = 0; j < size2; j++) {
                    a_[i][j] = (float *) malloc( size3 * sizeof(int) );
             //    a_[i][j] = new float[size3];
                        for(k = 0; k < size3; k++) {
                                a_[i][j][k] = 0;
                        }
                }
        }
        _size1 = size1;
        _size2 = size2;
        _size3 = size3;
        cout << "array created" << endl;
}

Array::~Array() {
        int i,j;
        for(i = 0; i < _size1; i++) {
                for(j = 0; j < _size2; j++)
                        delete a_[i][j];
                delete a_[i];
        }
        cout << "array deleted" << endl;
}

int Array::getSize1(){
    return _size1;
}

 int Array::getSize2(){
     return _size2;
 }

 int Array::getSize3(){
     return _size3;
 }

bool Array::setValue(int x, int y, int z, float value) {
        if(x >= _size1)
                return true;
        if(y >= _size2)
                return true;
        if(z >= _size3)
                return true;
        a_[x][y][z] = value;
        return false;
}
   
float Array::getValue(int x, int y, int z) {
     if(x>=_size1 || y>=_size2 || z>=_size3){
         cout << "index out of range" << endl;
         return 0;
     }
     return a_[x][y][z];
}

Array &Array::operator=(Array &right){
       int i,j,k; 
       if(&right != this)
       {
           delete [] a_; 
           _size1 = right.getSize1(); 
           _size2 = right.getSize2(); 
           _size3 = right.getSize3(); 
           a_ = (float ***)malloc(_size1*_size2*_size3);
           assert(a_ != 0);

           for(i=0; i<_size1; i++){
              for(j=0; j<_size2; j++){
                 for(k=0; k<_size3; k++){
                  a_[i][j][k] = right[i][j][k]; //  вот здесь проблема!!!
                 }
              }
           }
                 }
        return *this;
}

int Array::operator!=(Array &right)
{
        if(_size1 != right.getSize1() || _size2 != right.getSize2() || _size3 != right.getSize3())
                return 1;

        int i,j,k;
        for(i=0; i<_size1; ++i)
                for(j=0; j<_size2; ++j)
                        for(k=0; k<_size3; ++k)
                                if(a_[i][j][k] != right[i][j][k]) return 1;

        return 0;
 }

float** &Array::operator [](int i)
    {
       return a_[i];
    }


 

PM   Вверх
Леопольд
Дата 6.10.2010, 09:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



ElKa, c двумерными массивами код уже  сложно читать, а с тремя измерениями становится совсем тяжко, что чревато багами.

Индексы лучше переименовать в column, row, dept (или x, y ,z) во всём коде.

Если производительность не критична, то можно попробовать уйти от трехмерных массивов. Например, использовать что-то типа std::map<Point3d, float>.

IMHO логика в Array::setValue извращённая, если выход за границы, возвращает true, если всё ОК, возвращает false.

Макроса assert в релизе обычно нет (#define NDEBUG). Проверять им что недостаточно памяти не стоит.

Использовать malloc a потом delete[], это, по моему уже UB(undefined behaviour). Вместо malloc надо использовать new[]; Вызывает подозрение что на три выделения памяти делается два delete (а не три).

Если есть возможность то лучше использовать исключения (или assert, если позволяет специфика приложения) в Array::getValue и Array::setValue. Исключения более универсальны, assert не обработаешь, но зато нет накладных расходов.

В Array::operator= утечка памяти. Вместо трёх delete, всего один. И вообще, возникает ощущение что код писали как в мульте "Простоквашино" писали письмо. Строчку ты, строчку твой кот, а всё остальное Шарик... smile
Код
       a_ = (float ***)malloc( size1 * sizeof(int));
       // **a_ = new float[size1];
        for(i = 0; i < size1; i++) {
            a_[i] = (float **) malloc( size2 * sizeof(int) );
         //*a_[i] = new float[size2];
                for(j = 0; j < size2; j++) {
                    a_[i][j] = (float *) malloc( size3 * sizeof(int) );
             //    a_[i][j] = new float[size3];
                        for(k = 0; k < size3; k++) {
                                a_[i][j][k] = 0;
                        }
                }
        }
Код
a_ = (float ***)malloc(_size1*_size2*_size3);


Цитата(ElKa @  5.10.2010,  22:54 Найти цитируемый пост)
посмотрите пожалуйста код
Возникает ощущение что ты сама его не смотрела. Видимо практикуешь "слепой" десятипальцевый набор с завязанными глазами.. smile

P.S.
А может это просто стёб? Бывает и такое. Весьма похоже, надо сказать.

Это сообщение отредактировал(а) Леопольд - 6.10.2010, 10:25


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
Леопольд
Дата 6.10.2010, 12:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Если оно надо, то можно допилить.

Код

#ifndef MULTI_ARRAY_HPP
#define MULTI_ARRAY_HPP

#include <cassert>
#include <cstdlib>
#include <cstring>

#include <stdexcept>
#include <algorithm>

template<typename T, std::size_t dimension>
class MultiArray
{
private:
    friend class MultiArray<T, dimension + 1>;

    T * m_data_;

    // lArg must not be zero
    static inline std::size_t multiply_(std::size_t lArg, std::size_t rArg)
    {
        std::size_t product = lArg * rArg;
        if(product / lArg != rArg)
        {
            throw std::overflow_error("MultiArray: std::size_t overflow");
        }
        return product;
    }

    static void calculateSizes_(std::size_t const (&init)[dimension], std::size_t (&sizes)[dimension])
    {
        sizes[dimension - 1] = init[dimension - 1];
        for(std::size_t i = 1; i < dimension; ++i)
        {
            std::size_t const next = dimension - i - 1;
            std::size_t const curr = dimension - i;

            sizes[next] = multiply_(sizes[curr], init[next]);
            if(sizes[next] == 0)
            {
                throw std::length_error("MultiArray: zero length");
            }
        }
    }

    static T * alloc_(std::size_t const (&init)[dimension])
    {
        std::size_t sizes_[dimension];
        calculateSizes_(init, sizes_);

        //sizes_[0] contains the array's total size
        std::size_t const sizeofPayload_ = multiply_(sizes_[0], sizeof(T));
        std::size_t const sizeofWithoutPayload_ = sizeof(std::size_t) * (dimension + 2);

        std::size_t * buffer_ = static_cast<std::size_t *>(::malloc(sizeofWithoutPayload_ + sizeofPayload_));
        if(buffer_ == NULL)
        {
            throw std::bad_alloc();
        }

        // init data buffer_
        buffer_[0] = dimension;
        std::copy(sizes_, sizes_ + dimension, buffer_ + 1);
        buffer_[dimension + 1] = 1;

        // construct data
        T * payload_ = reinterpret_cast<T *>(buffer_ + dimension + 2);
        for(std::size_t i = 0; i < sizes_[0]; ++i)
        {
            new(payload_ + i) T();
        }

        return payload_;
    }

    static T * alloc_(MultiArray const& copy)
    {
        std::size_t const sizeofWithoutPayload_ = sizeof(std::size_t) * (dimension + 2);
        std::size_t const sizeofPayload_ = copy.size() * sizeof(T);

        std::size_t * buffer_ = static_cast<std::size_t *>(::malloc(sizeofWithoutPayload_ + sizeofPayload_));
        if(buffer_ == NULL)
        {
            throw std::bad_alloc();
        }
        std::size_t * copyBuffer_ = reinterpret_cast<std::size_t *>(copy.m_data_) - dimension - 2;
        std::copy(copyBuffer_, copyBuffer_ + dimension + 2, buffer_);

        // construct data
        T * payload_ = reinterpret_cast<T *>(buffer_ + dimension + 2);
        std::copy(copy.m_data_, copy.m_data_ + copy.size(), payload_);

        return payload_;
    }

    void destroy_() throw()
    {
        std::size_t const size_ = this->size();
        for(std::size_t i = 0; i < size_; ++i)
        {
            this->m_data_[i].~T();
        }
        std::size_t * rawMemory_ = reinterpret_cast<std::size_t *>(this->m_data_) - dimension - 2;
        ::free(rawMemory_);
    }

    struct Proxy_
    {
        std::size_t * m_sizes;
        T * m_data;

        Proxy_(std::size_t * sizes, T * data) :
            m_sizes(sizes), m_data(data)
        {}

        typename MultiArray<T, dimension - 1>::Proxy_ operator[] (std::size_t i)
        {
            T * leftBound = this->m_data;
            T * rightBound = this->m_data + this->m_sizes[0] - 1;

            std::size_t * sizes_ = this->m_sizes + 1;
            T * data_ = leftBound + multiply_(sizes_[0], i);
            if(data_ < leftBound || rightBound < data_)
            {
                throw std::range_error("MultiArray: out of bounds");
            }
            return MultiArray<T, dimension - 1>::getProxy_(sizes_, data_);
        }

        std::size_t size() const
        {
            return *this->m_sizes[0];
        }

        Proxy_ & operator=(Proxy_ const& rArg)
        {
            std::size_t const sizeofThis = this->m_sizes[0];
            std::size_t const sizeofThat = rArg.m_sizes[0];
            if(sizeofThis != sizeofThat)
            {
                throw std::length_error("MultiArray: unequal lenght");
            }
            std::copy(rArg.m_data, rArg.m_data + sizeofThat, this->m_data);

            return *this;
        }
    };

    struct NothrowProxy_
    {
        std::size_t * m_sizes;
        T * m_data;

        MultiArray *const m_parent;

        NothrowProxy_(std::size_t * sizes, T * data, MultiArray *const parent = NULL) :
            m_sizes(sizes), m_data(data), m_parent(parent)
        {}

        typename MultiArray<T, dimension - 1>::NothrowProxy_ operator[] (std::size_t i)
        {
            std::size_t * sizes_ = this->m_sizes + 1;
            T * data_ = this->m_data + sizes_[0] * i;
            return MultiArray<T, dimension - 1>::getNothrowProxy_(sizes_, data_);
        }

        std::size_t size() const
        {
            return this->m_sizes[0];
        }

        NothrowProxy_ & operator=(NothrowProxy_ const& rArg)
        {
            std::size_t const sizeofThat = rArg.m_sizes[0];
            std::copy(rArg.m_data, rArg.m_data + sizeofThat, this->m_data);

            return *this;
        }

//        TODO: array copy
        NothrowProxy_ & operator=(MultiArray const& copy)
        {
            if(this->m_parent != NULL)
            {
                T * buffer_ = alloc_(copy);
                this->m_parent->destroy_();
                this->m_parent->m_data_ = buffer_;
            }

            return *this;
        }

        void reshape(std::size_t const (&init)[dimension])
        {
            std::size_t sizes_[dimension];
            calculateSizes_(init, sizes_);

            //sizes_[0] contains the array's total size
            std::size_t * buffer_ = reinterpret_cast<std::size_t *>(this->m_data) - 1 - dimension;
            std::copy(sizes_ + 1, sizes_ + dimension, buffer_ + 1);
        }
    };

    static Proxy_ getProxy_(std::size_t * sizes, T * data)
    {
        return Proxy_(sizes, data);
    }

    static NothrowProxy_ getNothrowProxy_(std::size_t * sizes, T * data)
    {
        return NothrowProxy_(sizes, data);
    }

public:

    MultiArray(std::size_t const (&init)[dimension]) :
        m_data_(alloc_(init))
    {}

    MultiArray(MultiArray const& copy) :
        m_data_(alloc_(copy))
    {}

    typename MultiArray<T, dimension - 1>::Proxy_ operator[] (std::size_t i)
    {
        std::size_t * sizes_ = reinterpret_cast<std::size_t *>(this->m_data_) - dimension - 1;
        T * leftBound = this->m_data_;
        T * rightBound = this->m_data_ + sizes_[0] - 1;

        ++sizes_;
        T * data_ = leftBound + multiply_(sizes_[0], i);
        if(data_ < leftBound || rightBound < data_)
        {
            throw std::range_error("MultiArray: out of bounds");
        }
        return MultiArray<T, dimension - 1>::getProxy_(sizes_, data_);
    }

    NothrowProxy_ operator() (std::nothrow_t const&)
    {
        std::size_t * sizes_ = reinterpret_cast<std::size_t *>(this->m_data_) - dimension - 1;
        return NothrowProxy_(sizes_, this->m_data_, this);
    }

    MultiArray & operator= (MultiArray const& copy)
    {
        T * buffer_ = alloc_(copy);
        this->destroy_();
        this->m_data_ = buffer_;

        return *this;
    }

    void reshape(std::size_t const (&init)[dimension])
    {
        std::size_t sizes_[dimension];
        calculateSizes_(init, sizes_);

        //sizes_[0] contains the array's total size
        std::size_t * buffer_ = reinterpret_cast<std::size_t *>(this->m_data_) - 1 - dimension;
        if(sizes_[0] != buffer_[0])
        {
            throw std::invalid_argument("MultiArray: reshape unequal length");
        }

        std::copy(sizes_ + 1, sizes_ + dimension, buffer_ + 1);
    }

    ~MultiArray()
    {
        this->destroy_();
    }

    std::size_t size() const
    {
        return *(reinterpret_cast<std::size_t *>(this->m_data_) - dimension - 1);
    }
};

template<typename T>
class MultiArray<T, 0>
{
private:
    MultiArray(MultiArray const&);
    MultiArray & operator=(MultiArray const&);

    friend class MultiArray<T, 1>;

    typedef T & Proxy_;
    typedef T & NothrowProxy_;

    static Proxy_ getProxy_(std::size_t *, T * data)
    {
        return *data;
    }

    static NothrowProxy_ getNothrowProxy_(std::size_t *, T * data)
    {
        return *data;
    }

};

#endif
Код
#include <iostream>
#include <string>

#include <boost/multi_array.hpp>
#include <boost/lexical_cast.hpp>

#include "multi_array.hpp"

inline void testSpeed ()
{
    static std::size_t nativeArray[100][100][100];
    clock_t start = clock();
    for(std::size_t ni = 0; ni < 100; ++ni )
        for(std::size_t i = 0; i < 100; ++i)
            for(std::size_t j = 0; j < 100; ++j)
                for(std::size_t k = 0; k <100; ++k)
                    nativeArray[i][j][k] = 0;
    clock_t stop = clock();
    std::cout << "nativeArray: " << double((stop - start)) / CLOCKS_PER_SEC << " seconds" << std::endl;

    start = clock();
    typedef boost::multi_array<std::size_t, 3> array_type;
    typedef array_type::index index;
    array_type boostArray(boost::extents[100][100][100]);

    for(std::size_t ni = 0; ni < 100; ++ni )
        for(std::size_t i = 0; i < 100; ++i)
            for(std::size_t j = 0; j < 100; ++j)
                for(std::size_t k = 0; k <100; ++k)
                    boostArray[i][j][k] = 0;
    stop = clock();
    std::cout << "boostArray: " << double((stop - start)) / CLOCKS_PER_SEC << " seconds" << std::endl;

    start = clock();
    std::size_t init[] = {100, 100, 100};
    MultiArray<std::size_t, 3> myArray(init);

    for(std::size_t ni = 0; ni < 100; ++ni )
        for(std::size_t i = 0; i < 100; ++i)
            for(std::size_t j = 0; j < 100; ++j)
                for(std::size_t k = 0; k <100; ++k)
                    myArray(std::nothrow)[i][j][k] = 0;
    stop = clock();
    std::cout << "myArray(std::nothrow): " << double((stop - start)) / CLOCKS_PER_SEC << " seconds" << std::endl;

    start = clock();
    for(std::size_t ni = 0; ni < 100; ++ni )
        for(std::size_t i = 0; i < 100; ++i)
            for(std::size_t j = 0; j < 100; ++j)
                for(std::size_t k = 0; k <100; ++k)
                    myArray[i][j][k] = 0;
    stop = clock();
    std::cout << "myArray: " << double((stop - start)) / CLOCKS_PER_SEC << " seconds" << std::endl;
}

std::size_t testNo = 0;
bool printPassed = true;
#define BOOL_TEST(EXPR) \
++testNo;\
if(EXPR)\
{\
    if(printPassed)\
    {\
        std::cerr << "test " << testNo << ": PASSED (" #EXPR ")\n" << std::flush;  \
    }\
}\
else\
{\
    std::cerr << "test " << testNo << ": FAILED (" #EXPR ")\n" << std::flush;  \
}

inline void testSuite()
{
    {
        std::size_t init[] = {2, 5, 3};
        MultiArray<std::size_t, 3> array(init);

        std::size_t d0 = 0;
        std::size_t d1 = 0;
        std::size_t d2 = 0;

        BOOL_TEST(array.size() == 30)

        for(d0 = 0; d0 < init[0]; ++d0)
            for(d1 = 0; d1 < init[1]; ++d1)
                for(d2 = 0; d2 < init[2]; ++d2)
                {
                    array[d0][d1][d2] = d0 * 100 + d1 * 10 + d2;
                }

        for(d0 = 0; d0 < init[0]; ++d0)
            for(d1 = 0; d1 < init[1]; ++d1)
                for(d2 = 0; d2 < init[2]; ++d2)
                {
                    BOOL_TEST(array[d0][d1][d2] == d0 * 100 + d1 * 10 + d2);
                }

        array[0] = array[1];
        for(d1 = 0; d1 < init[1]; ++d1)
            for(d2 = 0; d2 < init[2]; ++d2)
            {
                BOOL_TEST(array[0][d1][d2] == array[1][d1][d2]);
            }

        array[0][0] = array[0][1];
        for(d2 = 0; d2 < init[2]; ++d2)
        {
            BOOL_TEST(array[0][0][d2] == array[0][1][d2]);
        }

        array[0][0][0] = array[0][0][1];
        BOOL_TEST(array[0][0][0] == array[0][0][1]);
    }

    {
        std::size_t init[] = {2, 3};
        MultiArray<std::size_t, 2> array(init);

        std::size_t d0 = 0;
        std::size_t d1 = 0;

        for(d0 = 0; d0 < init[0]; ++d0)
            for(d1 = 0; d1 < init[1]; ++d1)
            {
                array[d0][d1] = d0 * 10 + d1;
            }

        for(d0 = 0; d0 < init[0]; ++d0)
            for(d1 = 0; d1 < init[1]; ++d1)
            {
                BOOL_TEST(array[d0][d1] == d0 * 10 + d1);
            }

        std::size_t newShape1[] = {3, 2};
        array.reshape(newShape1);
        BOOL_TEST(array[0][0] == 00);
        BOOL_TEST(array[0][1] == 01);
        BOOL_TEST(array[1][0] == 02);
        BOOL_TEST(array[1][1] == 10);
        BOOL_TEST(array[2][0] == 11);
        BOOL_TEST(array[2][1] == 12);

        std::size_t newShape2[] = {1, 6};
        array.reshape(newShape2);
        BOOL_TEST(array[0][0] == 00);
        BOOL_TEST(array[0][1] == 01);
        BOOL_TEST(array[0][2] == 02);
        BOOL_TEST(array[0][3] == 10);
        BOOL_TEST(array[0][4] == 11);
        BOOL_TEST(array[0][5] == 12);

        std::size_t newShape3[] = {6, 1};
        array.reshape(newShape3);
        BOOL_TEST(array[0][0] == 00);
        BOOL_TEST(array[1][0] == 01);
        BOOL_TEST(array[2][0] == 02);
        BOOL_TEST(array[3][0] == 10);
        BOOL_TEST(array[4][0] == 11);
        BOOL_TEST(array[5][0] == 12);
    }

    {
        std::size_t init[] = {2, 5, 3};
        MultiArray<std::size_t, 3> array(init);

        std::size_t d0 = 0;
        std::size_t d1 = 0;
        std::size_t d2 = 0;

        BOOL_TEST(array(std::nothrow).size() == 30)

        for(d0 = 0; d0 < init[0]; ++d0)
            for(d1 = 0; d1 < init[1]; ++d1)
                for(d2 = 0; d2 < init[2]; ++d2)
                {
                    array(std::nothrow)[d0][d1][d2] = d0 * 100 + d1 * 10 + d2;
                }

        for(d0 = 0; d0 < init[0]; ++d0)
            for(d1 = 0; d1 < init[1]; ++d1)
                for(d2 = 0; d2 < init[2]; ++d2)
                {
                    BOOL_TEST(array(std::nothrow)[d0][d1][d2] == d0 * 100 + d1 * 10 + d2);
                }

        array(std::nothrow)[0] = array(std::nothrow)[1];
        for(d1 = 0; d1 < init[1]; ++d1)
            for(d2 = 0; d2 < init[2]; ++d2)
            {
                BOOL_TEST(array(std::nothrow)[0][d1][d2] == array(std::nothrow)[1][d1][d2]);
            }

        array(std::nothrow)[0][0] = array(std::nothrow)[0][1];
        for(d2 = 0; d2 < init[2]; ++d2)
        {
            BOOL_TEST(array(std::nothrow)[0][0][d2] == array(std::nothrow)[0][1][d2]);
        }

        array(std::nothrow)[0][0][0] = array(std::nothrow)[0][0][1];
        BOOL_TEST(array(std::nothrow)[0][0][0] == array(std::nothrow)[0][0][1]);
    }

    {
        std::size_t init[] = {2, 3};
        MultiArray<std::size_t, 2> array(init);

        std::size_t d0 = 0;
        std::size_t d1 = 0;

        for(d0 = 0; d0 < init[0]; ++d0)
            for(d1 = 0; d1 < init[1]; ++d1)
            {
                array(std::nothrow)[d0][d1] = d0 * 10 + d1;
            }

        for(d0 = 0; d0 < init[0]; ++d0)
            for(d1 = 0; d1 < init[1]; ++d1)
            {
                BOOL_TEST(array(std::nothrow)[d0][d1] == d0 * 10 + d1);
            }

        std::size_t newShape1[] = {3, 2};
        array(std::nothrow).reshape(newShape1);
        BOOL_TEST(array(std::nothrow)[0][0] == 00);
        BOOL_TEST(array(std::nothrow)[0][1] == 01);
        BOOL_TEST(array(std::nothrow)[1][0] == 02);
        BOOL_TEST(array(std::nothrow)[1][1] == 10);
        BOOL_TEST(array(std::nothrow)[2][0] == 11);
        BOOL_TEST(array(std::nothrow)[2][1] == 12);

        std::size_t newShape2[] = {1, 6};
        array(std::nothrow).reshape(newShape2);
        BOOL_TEST(array(std::nothrow)[0][0] == 00);
        BOOL_TEST(array(std::nothrow)[0][1] == 01);
        BOOL_TEST(array(std::nothrow)[0][2] == 02);
        BOOL_TEST(array(std::nothrow)[0][3] == 10);
        BOOL_TEST(array(std::nothrow)[0][4] == 11);
        BOOL_TEST(array(std::nothrow)[0][5] == 12);

        std::size_t newShape3[] = {6, 1};
        array(std::nothrow).reshape(newShape3);
        BOOL_TEST(array(std::nothrow)[0][0] == 00);
        BOOL_TEST(array(std::nothrow)[1][0] == 01);
        BOOL_TEST(array(std::nothrow)[2][0] == 02);
        BOOL_TEST(array(std::nothrow)[3][0] == 10);
        BOOL_TEST(array(std::nothrow)[4][0] == 11);
        BOOL_TEST(array(std::nothrow)[5][0] == 12);

        MultiArray<std::size_t, 2> array1(init);
        array1(std::nothrow) = array;
        BOOL_TEST(array1[0][0] == array(std::nothrow)[0][0]);
        BOOL_TEST(array1[1][0] == array(std::nothrow)[1][0]);
        BOOL_TEST(array1[2][0] == array(std::nothrow)[2][0]);
        BOOL_TEST(array1[3][0] == array(std::nothrow)[3][0]);
        BOOL_TEST(array1[4][0] == array(std::nothrow)[4][0]);
        BOOL_TEST(array1[5][0] == array(std::nothrow)[5][0]);

        array(std::nothrow).reshape(newShape2);
        array1 = array;
        BOOL_TEST(array(std::nothrow)[0][0] == array1[0][0]);
        BOOL_TEST(array(std::nothrow)[0][1] == array1[0][1]);
        BOOL_TEST(array(std::nothrow)[0][2] == array1[0][2]);
        BOOL_TEST(array(std::nothrow)[0][3] == array1[0][3]);
        BOOL_TEST(array(std::nothrow)[0][4] == array1[0][4]);
        BOOL_TEST(array(std::nothrow)[0][5] == array1[0][5]);
    }
}

int main()
{
    testSuite();

    testSpeed();

    return 0;
}

LWS

Это сообщение отредактировал(а) Леопольд - 31.10.2010, 13:30


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1251 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.