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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Оптимизация функции, перевода числа в бинарную матрицу 
:(
    Опции темы
cupper
Дата 5.6.2009, 20:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Предыстория:
делаю алгоритм штрассена умножения матриц, использую его для последовательного возведения в степень (почему именно штрассена - такое задание) до тех пор пока не получу уже существующую матрицу. Таким образом перебираем все матрицы определенной размерности. Матрицы бинарного вида.
Например матрицы размерности 4 идут от
Код

0000
0000
0000
0000

до
Код

1111
1111
1111
1111

матрицы перебераю следующим образом.
В цикде от 0 до максимального значения определенной размерности матрицы (в случае размерности 4 - это 65535), каждое число инвертирую в бинарную матрицу следующим образом:
Код

int **creatMatrixFromNumber (int **matrix, const int matrixNum, const size_t len){
    int temp=matrixNum;
    for (int i=len-1; i>=0; --i){
        for (int j=len-1; j>=0; --j){
            matrix[i][j]=temp%2;
            temp>>=1;
        }
        
    }
    return matrix;
}

Мне сказали что это самый медленный способ получения из числа матрицы. Как можно по другому, оптимизировнно ?
PM MAIL   Вверх
mes
Дата 5.6.2009, 20:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



а в каких пределах изменяется размерность матрицы ?
пояснение: показанная выше бинарная матрица может  быть представлена обычным 16ти битным числом,
и тогда перебор всех матриц будет заключаться в циклическом инкрементировании такой переменной.
smile


Это сообщение отредактировал(а) mes - 5.6.2009, 21:19


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


Опытный
**


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

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



эм, размерность..., Вообще несмотря на то что сделано для любой, но фактически только для размерности 4, потому что для размерности 8 это уже кластер нужен чтобы посчитать 2^64 матриц smile
PM MAIL   Вверх
math64
Дата 5.6.2009, 21:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

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



В приведённом примере вместо temp%2 нужно temp&1.
Но декорировать до битов нет необходимости.
Код

class BitMatrix {
  int n; // 1 ... 32
  int* data;
public:
  BitMatrix(int _n) : n(_n), data(new int[_n]) { }
  BitMatrix& operator *(const BitMatrix& b) {
    for(int i = 0; i < n; i++) {
       int old = data[i];
       int res = 0;
       for(int j = 0; j < n; j++) {
          if((old & 1) != 0) // Умножение заменяется на if
            res ^= b.data[j]; // Сложение по модулю 2 всех битов строки сразу
          old >>= 1;
       }
       data[i] = res;
    }
  }
  ...
};

Т.е. вычисляем целую строку за раз (вместо трёх for только два). 
PM   Вверх
cupper
Дата 5.6.2009, 22:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



ООП эт конечно хорошо, но тут оно излишне.
на счет & спс.
А вот приведеный вами код я чтото немогу понять, это ведь не перевод числа в матрицу, верно ? это умножение уже, а оно ненужно. 
PM MAIL   Вверх
mes
Дата 5.6.2009, 22:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(cupper @  5.6.2009,  19:15 Найти цитируемый пост)
 каждое число инвертирую в бинарную матрицу следующим образом:

Цитата(cupper @  5.6.2009,  19:15 Найти цитируемый пост)
Мне сказали что это самый медленный способ получения из числа матрицы. Как можно по другому, оптимизировнно ? 

Можно работать с числом напрямую, рассматривая его как матрицу.  smile 


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


Опытный
**


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

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



конечно можно если используетться или специальный алгоритм для чисел или извратиться для простого метода. Но для метода штрасена этого неполучиться.
PM MAIL   Вверх
mes
Дата 6.6.2009, 00:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(cupper @  5.6.2009,  23:15 Найти цитируемый пост)
Но для метода штрасена этого неполучиться. 

И с чего это вдруг ?!

Добавлено через 1 минуту и 15 секунд
приведите ту часть кода, которая оперирует с готовой матрицей.


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


Опытный
**


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

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



Код

int** multiplicationOfMatrixes (int ** C, int ** A, int ** B, const size_t len){
    int lenC = len/2;
if (len > 1){

    int ** a = initMatrix (A, 1, len);
    int ** b = initMatrix (A, 2, len);
    int ** c = initMatrix (A, 3, len);
    int ** d = initMatrix (A, 4, len);
    int ** e = initMatrix (B, 1, len);
    int ** g = initMatrix (B, 2, len);
    int ** f = initMatrix (B, 3, len);
    int ** h = initMatrix (B, 4, len);

    int ** A2 = matrixOperation (a, b, '+', lenC);
    int ** A3 = matrixOperation (c, d, '+', lenC);
    int ** A5 = matrixOperation (a, d, '+', lenC);
    int ** A6 = matrixOperation (b, d, '-', lenC);//-
    int ** A7 = matrixOperation (a, c, '-', lenC);//-
    int ** B1 = matrixOperation (g, h, '-', lenC);//-
    int ** B4 = matrixOperation (f, e, '-', lenC);//-
    int ** B5 = matrixOperation (e, h, '+', lenC);
    int ** B6 = matrixOperation (f, h, '+', lenC);
    int ** B7 = matrixOperation (e, g, '+', lenC);

    int **P1 = new int * [lenC];
     for (size_t i = 0; i < lenC; i++){
        P1[i] = new int [lenC];
    }
    int **P2 = new int * [lenC];
     for (size_t i = 0; i < lenC; i++){
        P2[i] = new int [lenC];
    }
    int **P3 = new int * [lenC];
     for (size_t i = 0; i < lenC; i++){
        P3[i] = new int [lenC];
    }
    int **P4 = new int * [lenC];
     for (size_t i = 0; i < lenC; i++){
        P4[i] = new int [lenC];
    }
    int **P5 = new int * [lenC];
     for (size_t i = 0; i < lenC; i++){
        P5[i] = new int [lenC];
    }
    int **P6 = new int * [lenC];
     for (size_t i = 0; i < lenC; i++){
        P6[i] = new int [lenC];
    }
    int **P7 = new int * [lenC];
     for (size_t i = 0; i < lenC; i++){
        P7[i] = new int [lenC];
    }
    multiplicationOfMatrixes (P1, a, B1, lenC);
    multiplicationOfMatrixes (P2, A2, h, lenC);
    multiplicationOfMatrixes (P3, A3, e, lenC);
    multiplicationOfMatrixes (P4, d, B4, lenC);
    multiplicationOfMatrixes (P5, A5, B5, lenC);
    multiplicationOfMatrixes (P6, A6, B6, lenC);
    multiplicationOfMatrixes (P7, A7, B7, lenC);
    
    int **s;
    int **t;
    int ** r = matrixOperation (s = matrixOperation(P5, P4, '+', lenC), t = matrixOperation(P6, P2, '-', lenC), '+', lenC);
    deleteMatrix(s, lenC);
    deleteMatrix(t, lenC);
    int ** u = matrixOperation (s = matrixOperation(P5, P3, '-', lenC), t = matrixOperation(P1, P7, '-', lenC), '+', lenC);
    deleteMatrix(s, lenC);
    deleteMatrix(t, lenC);
    s = matrixOperation (P1, P2, '+', lenC);
    t = matrixOperation (P3, P4, '+', lenC);

    for (size_t i=0; i<lenC; ++i){
        for (size_t j=0; j<lenC; ++j){
            C[i][j] = r[i][j];
            C[i][j + lenC] = s[i][j];
            C[i + lenC][j] = t[i][j];
            C[i + lenC][j + lenC] = u[i][j];
        }
    }

    deleteMatrix (r, lenC);
    deleteMatrix (s, lenC);
    deleteMatrix (t, lenC);
    deleteMatrix (u, lenC);

    deleteMatrix (A2, lenC);
    deleteMatrix (A3, lenC);
    deleteMatrix (A5, lenC);
    deleteMatrix (A6, lenC);
    deleteMatrix (A7, lenC);

    deleteMatrix (B1, lenC);
    deleteMatrix (B4, lenC);
    deleteMatrix (B5, lenC);
    deleteMatrix (B6, lenC);
    deleteMatrix (B7, lenC);

    deleteMatrix (P1, lenC);
    deleteMatrix (P2, lenC);
    deleteMatrix (P3, lenC);
    deleteMatrix (P4, lenC);
    deleteMatrix (P5, lenC);
    deleteMatrix (P6, lenC);
    deleteMatrix (P7, lenC);

    deleteMatrix (a, lenC);
    deleteMatrix (b, lenC);
    deleteMatrix (c, lenC);
    deleteMatrix (d, lenC);
    deleteMatrix (e, lenC);
    deleteMatrix (g, lenC);
    deleteMatrix (f, lenC);
    deleteMatrix (h, lenC);
}
else{
    C[0][0] = A[0][0] * B[0][0];
}
    return C;
}

int** matrixOperation (int ** A, int ** B , const char operation, const size_t len){
    int ** P = new int* [len];
    for (size_t i=0; i<len; ++i){
        P[i] = new int [len];
    }
    switch ((int)operation){
        case (int)'+':
            matrixSum (P, A, B, len);
            break;
        case (int)'-':
            matrixDif (P, A, B, len);
            break;
        default:
            cerr<<"Unknown option: "<<operation<<endl;
    }
    return P;
}

int** matrixSum (int ** P, int ** A, int ** B, const size_t len){
    for (int i=0; i<len; ++i){
        for (int j=0; j<len; ++j){
            P[i][j] = A[i][j] + B[i][j];
        }
    }
    return P;
}

int** matrixDif (int ** P, int ** A, int ** B, const size_t len){
    for (int i=0; i<len; ++i){
        for (int j=0; j<len; ++j){
            P[i][j] = A[i][j] - B[i][j];
        }
    }
    return P;
}
int** initMatrix (int ** A, const unsigned int period, const size_t len){    
    unsigned int lenC = len/2;
    int ** C = new int* [lenC];
    for (size_t i=0; i<lenC; ++i){
        C[i] = new int [lenC];
    }
    switch (period){
        case 1:
            for (int i=0; i<lenC; ++i){
                for (int j=0; j<lenC; ++j){
                    C[i][j] = A[i][j];
                }
            }
            break;
        case 2:
            for (int i=0; i<lenC; ++i){
                for (int j=0; j<lenC; ++j){
                    C[i][j] = A[i][(len>>1) + j];
                }
            }
            break;
        case 3:
            for (int i=0; i<lenC; ++i){
                for (int j=0; j<lenC; ++j){
                    C[i][j] = A[(len>>1) + i][j];
                }
            }
            break;
        case 4:
            for (int i=0; i<lenC; ++i){
                for (int j=0; j<lenC; ++j){
                    C[i][j] = A[(len>>1) + i][(len>>1) + j];
                }
            }
            break;
        default:
            cerr<<"Error period "<<period<<endl;
    }
    return C;
}
void deleteMatrix (int ** delMatrix, const size_t len){
    for (int i = len - 1; i >= 0; --i){
        delete[] delMatrix[i];

    }
    delete[] delMatrix;
}
bool equalityMatrix (vector<int>& vec, int ** matrix, size_t len){
    for (size_t i=0; i<len; ++i){
        for (size_t j=0; j<len; ++j){
            if (vec[len*i + j] != matrix[i][j]){
                return 1;
            }
        }
    }
    return 0;
}

int equalityMatrixInBD (vector<vector<int> > & vec, int ** matrix, size_t len){
    for (size_t i = 0; i<vec.size(); ++i){
        if (equalityMatrix(vec[i], matrix, len) == 0)
            return i;
    }
    return -1;
}

void addMatrixInBD (vector<vector<int> > & vec, int ** matrix, size_t len){
    if (matrix == NULL){
        cerr<<"Matrix is NULL\n";
        return;
    }
    vector<int> temp;
    for (size_t i=0; i<len; ++i){
        for (int j=0; j<len; ++j){
            temp.push_back(matrix[i][j]);
        }
    }
    vec.push_back(temp);
}

если вы это сможите переделатьэто  для работы непосредственно с числом, тогда я обеими руками за чтобы назвать новый метод вашем именем smile
Этот алгоритм непредназначен для работы именно с бинарными матрицами он для любых матриц являебщихся квадратными, размерность которых являеться степени двойки. А вообще он на вики описан, довольно кратнко и ясно. 

Это сообщение отредактировал(а) cupper - 6.6.2009, 10:10
PM MAIL   Вверх
mes
Дата 6.6.2009, 12:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(cupper @  6.6.2009,  08:55 Найти цитируемый пост)
Этот алгоритм непредназначен для работы именно с бинарными матрицами

Знаете сам алгоритм не при чем. Он использует базовые операции с матрицей. А их, в том числе и хранение матрицы, можно оптимизировать под задачу.
Но даже без оптимизации они в любом случае должны быть реализованы.

Вот в частности ваша реализация сложения бинарной развернутой (т.е каждый бит представлен числом) матрицы

Цитата(cupper @  6.6.2009,  08:55 Найти цитируемый пост)
int** matrixSum (int ** P, int ** A, int ** B, const size_t len){
    for (int i=0; i<len; ++i){
        for (int j=0; j<len; ++j){
            P[i][j] = A[i][j] + B[i][j];
        }
    }
    return P;
}

не верна. Так как после такого сложения некоторые ячейки будут отличны от 0 и 1.
smile

Добавлено через 2 минуты и 16 секунд
код кстати  (пока правда сильно не копался в нем) вызывает опасения, из за обильного использования new/delete и обилия переменных, которые вполне заменялись бы массивом.





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


Опытный
**


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

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



маджиг пипл smile
короче люди ненадо лезть в алгоритм, мой вопрос описан в первом посту, больше нечего нетребуеться.
алгоритм и вся программа рабочая, работает правильно.
PM MAIL   Вверх
mes
Дата 6.6.2009, 18:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(cupper @  6.6.2009,  16:46 Найти цитируемый пост)
короче люди ненадо лезть в алгоритм, мой вопрос описан в первом посту, больше нечего нетребуеться.
алгоритм и вся программа рабочая, работает правильно. 

Цитата(cupper @  5.6.2009,  19:15 Найти цитируемый пост)
Как можно по другому, оптимизировнно ? 

В распаковке набора битов (числа) в набор чисел(массив) приведенной в Вашем примере фактически нечего оптимизировать. Все что можно (в частности замену модуля на and) там сумеет сделать сам компилятор.

Но с бинарной матрицей можно оперировать не разворачивая ее. И многие операции с упакованной матрицей могут быть быстрей, так как можно в реализации применять действие не к одному, а к набору битов.
 smile 
    



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


Опытный
**


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

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



Цитата(mes @ 6.6.2009,  18:39)
Но с бинарной матрицей можно оперировать не разворачивая ее. И многие операции с упакованной матрицей могут быть быстрей, так как можно в реализации применять действие не к одному, а к набору битов.
 smile

Я и неспорю что можно, но либо для спец. алгоритмво либо для обычного переборного. В данном алгоритме помино операции * и + есть операция -, которую нельзя заменить на + (-matrix), мы пытались сначало оптимизировать этот алгоритм для бинарных матриц, но труды были бесполезны. В итоге данный алгоритм для бинарных матриц можно применять только следующим образом:
на вход поступает две бинарный матрицы, на выходе получаеться НЕ бинарная матрица, которая бинаризуеться, путем замены всех ненулевых элементов на 1. Это единственный выход который мы смогли найти (найти в интернете). 
Если вы горитите что метод перевода числа в матрицу иначе, более оптимально, никак низя сделать, то возможно так оно и должно быть.

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


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

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



Поскольку по крайней мере в промежуночных результатах могут быть не только 0 и 1, производить вычисления в запакованном виде нельзя.
Оптимизировать можно только убирая лишние копирования и выделения памяти.
Матрицу хранить в виде одномерного массива.
Поскольку программируешь на C++, отказываться от ООП не имеет смысла.
Код

class Matrix() {
   int len;
   int shift;
   int* data;
   bool owner;
public:
   Matrix(int n) : len(n), shift(n), data(new int[n*n]), owner(true) { }
   Matrix(int n, int64 value) : len(n), shift(n), data(new int[n*n]), owner(true) { // n <= 8
      Set(value);
   }
   Matrix(const& Matrix& m) : len(m.len), shift(m.len), data(new int[len*len]), owner(true) {
      for(int i = 0; i < len; i++)
        for(int j = 0; j < len; j++)
          Set(i, j, m.Get(i,j));
   }
   Matrix(Matrix&m, int quater) : owner(false) {
     switch(quater) {
       case 0:
         len = m.len/2; shift = m.shift; data = m.data;
         break;
       case 1:
         len = m.len/2; shift = m.shift; data = m.data + len;
         break;
       case 2:
         len = m.len/2; shift = m.shift; data = m.data + shift * len;
         break;
       case 3:
         len = m.len/2; shift = m.shift; data = m.data + shift * (len + 1);
         break;
     }
   }
   ~Matrix() { if (owner) delete data; }
   int Get(int i, int j) { return data[i*shift+j]; }
   void Set(int i, int j, int v) { data[i*shift+j] = v; }
   void Set(int64 value) { // len <= 8
      for(int i = 0; i < len; i++)
        for(int j = 0; j < len; j++) {
          Set(i, j, value&1); value >>= 1;
        }
   }
   ...
};


Добавлено через 14 минут и 10 секунд
Цитата(cupper @  7.6.2009,  17:05 Найти цитируемый пост)
на вход поступает две бинарный матрицы, на выходе получаеться НЕ бинарная матрица, которая бинаризуеться, путем замены всех ненулевых элементов на 1. Это единственный выход который мы смогли найти (найти в интернете). 

При предложенной тобой бинаризации не будут выполняться законы:
Код

(A + B) + C = A + (B + C)
(A + B) * C = A * C + B * C
A * (B + C) = A * B + A * C

Правильное бинаризирование матрицы - оставить отолько последнюю цифру результата.
Умножение (обычное) для таких матриц в  упакованном виде я привёл в своём первом посте - только код operator*=,  а не operator* и забыл return *this;
Кстати, тогда operator+ и operator- будут иметь один и тот же код.
 
PM   Вверх
mes
Дата 7.6.2009, 23:10 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(cupper @  7.6.2009,  16:05 Найти цитируемый пост)
Если вы горитите что метод перевода числа в матрицу иначе, более оптимально, никак низя сделать, то возможно так оно и должно быть.

ловите примерчик для матрицы 4х4 (для остальных аналогично), оптимальней вряд ли получится :

Код

unsigned char matrix[4][4] = { 0 };
const unsigned char base[][4]  = { { 0,0,0,0 }, { 0,0,0,1 }, { 0,0,1,0 }, { 0,0,1,1 },
                                   { 0,1,0,0 }, { 0,1,0,1 }, { 0,1,1,0 }, { 0,1,1,1 },
                                   { 1,0,0,0 }, { 1,0,0,1 }, { 1,0,1,0 }, { 1,0,1,1 },
                                   { 1,1,0,0 }, { 1,1,0,1 }, { 1,1,1,0 }, { 1,1,1,1 },
                                 };
int main()
{

   unsigned value = 0x123F; // условное число, хранящее упакованную битовую матрицу: 0001 0010 0011  11111

   memcpy (matrix+0,  &base[value>>12 & 0xF], 4);
   memcpy (matrix+1,  &base[value>>8  & 0xF], 4);
   memcpy (matrix+2,  &base[value>>4  & 0xF], 4);
   memcpy (matrix+3,  &base[value>>0  & 0xF], 4);

   for (unsigned i=0; i<4; ++i)
   {
       for (unsigned j=0; j<4; ++j)
         std::cout << (int) matrix[i][j]<<" ";
       std::cout << std::endl;
   }

   return 0;
}


Это сообщение отредактировал(а) mes - 7.6.2009, 23:12


--------------------
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

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

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

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

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


 




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


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

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