ryoaro ohara
/
c95_AIchip
AIチップをmbedから駆動するためのプログラムです.
Diff: matrix.hpp
- Revision:
- 1:18e8ead6f188
diff -r 80ae2acaa6a1 -r 18e8ead6f188 matrix.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/matrix.hpp Sat Mar 16 14:54:57 2019 +0000 @@ -0,0 +1,1629 @@ +#include "mbed.h" +#include "matrix_const.hpp" +#ifndef INCLUDE_MATRIX +#define INCLUDE_MATRIX + +namespace mat +{ +template <typename TYPE> +class Matrix +{ + + public: + TYPE *data; + int height;//if height == 0 then dimension y is zero + int width;// + int channel;// + int insert_index;// + + void assert(int flag){ + if(! flag){ + printf("error has happend\n\r"); + } + } + /****************************************************************************************** + * Calcrate index from x,y,x axis + * ***************************************************************************************/ + int calc_pos(int x, int y, int d) + { + int pos = 0; + pos += d * (width * height); + pos += y * width; + pos += x; + return pos; + } + + // Constructor Create Matrix Instance + void initialize(int width, int height, int channel) + { + assert(channel > 0 && height > 0 && width > 0); + this->channel = channel; + this->height = height; + this->width = width; + this->data = (TYPE *)calloc(width * height * channel, sizeof(TYPE)); + this->insert_index = 0; + } + + /****************************************************************************************** + * Create 1D Matrix data, like a vector + * args + * width vector length + * ***************************************************************************************/ + Matrix(int width) + { + assert(width > 0); + initialize(width, 1, 1); + } + /****************************************************************************************** + * Create 2D Matrix data + * args + * width : matrix width + * height : matrix height + * ***************************************************************************************/ + Matrix(int width, int height) + { + assert(width > 0 && height > 0); + initialize(width, height, 1); + } + + /****************************************************************************************** + * Create 3D Matrix data + * args + * width : matrix width + * height : matrix height + * channel : matrix channel, in other word matrix depth + * ***************************************************************************************/ + Matrix(int width, int height, int channel) + { + assert(width > 0 && height > 0 && channel > 0); + initialize(width, height, channel); + } + + //Copy constructor + Matrix(const Matrix &obj) + { + this->width = obj.width; + this->height = obj.height; + this->channel = obj.channel; + this->insert_index = obj.insert_index; + + this->data = (TYPE *)calloc(obj.width * obj.height * obj.channel, sizeof(TYPE)); + for (int i = 0; i < (obj.width * obj.height * obj.channel); i++) + { + this->data[i] = obj.data[i]; + } + } + + //Copy + void operator=(const Matrix<TYPE> &obj) + { + this->width = obj.width; + this->height = obj.height; + this->channel = obj.channel; + this->insert_index = obj.insert_index; + + if (this->data != NULL) + { + free(this->data); + } + + this->data = data = (TYPE *)calloc(obj.width * obj.height * obj.channel, sizeof(TYPE)); + for (int i = 0; i < (obj.width * obj.height * obj.channel); i++) + { + this->data[i] = obj.data[i]; + } + } + + //Destructor + ~Matrix() + { + if (this->data != NULL) + { + free(this->data); + this->data = NULL; + } + } + + // Reshapes configure aspects + + /****************************************************************************************** + * Convert to 1D Matrix data, like a vector + * args + * width : vectot lengs + * return + * reshaped Matrix + * ***************************************************************************************/ + Matrix<TYPE> reshape(int width) + { + assert(this->width != 0 && this->height != 0 && this->channel != 0); + assertt((this->channel * this->height * this->width) == width); + + Matrix<TYPE> tmp(width, 1, 1); + for (int i = 0; i < this->width * this->height * this->channel; i++) + tmp.data[i] = this->data[i]; + + return tmp; + } + + /****************************************************************************************** + * Convert to 2D Matrix data + * args + * width : matrix width + * height : matrix height + * return + * reshaped Matrix + * ***************************************************************************************/ + Matrix<TYPE> reshape(int width, int height) + { + assert(this->width != 0 && this->height != 0 && this->channel != 0); + assert((this->channel * this->height * this->width) == width * height); + + Matrix<TYPE> tmp(width, height, 1); + for (int i = 0; i < width * height * channel; i++) + tmp.data[i] = this->data[i]; + + return tmp; + } + + /****************************************************************************************** + * Convert to 3D Matrix data + * args + * width : matrix width + * height : matrix height + * channel : matrix channel, in other word matrix depth + * return + * reshaped Matrix + * ***************************************************************************************/ + Matrix<TYPE> reshape(int width, int height, int channel) + { + assert(this->width != 0 && this->height != 0 && this->channel != 0); + assert((this->channel * this->height * this->width) == (channel * width * height)); + + Matrix<TYPE> tmp(width, height, channel); + for (int i = 0; i < width * height * channel; i++) + tmp.data[i] = this->data[i]; + + return tmp; + } + + /****************************************************************************************** + * Opt out Matrix datas + * ***************************************************************************************/ + void show(void) + { + for (int i = 0; i < this->channel; i++) + { + if (i > 1){ + printf("channel %d",i); + printf("\n\r"); + } + printf("["); + for (int j = 0; j < this->height; j++) + { + printf("["); + for (int k = 0; k < this->width; k++) + { + int ptr = (i * this->width * this->height) + (j * this->width) + k; + printf("%F ",(double)data[ptr].to_double()); //ごめんなさい + } + printf("]"); + if (j < this->height - 1) + { + printf("\n\r"); + } + } + printf("]"); + printf("\n\r"); + } + } + /****************************************************************************************** + * Opt out Matrix datas in 1/0 + * ***************************************************************************************/ + void show_bin(void) + { + for (int i = 0; i < this->channel; i++) + { + if (i > 1){ + printf("channel %d",i ); + printf("\n\r"); + } + printf("["); + for (int j = 0; j < this->height; j++) + { + printf("["); + for (int k = 0; k < this->width; k++) + { + int ptr = (i * this->width * this->height) + (j * this->width) + k; + printf(" %d",((data[ptr] > 0) ? 1 : 0)); + } + printf("]"); + if (j < this->height - 1) + { + printf("\n\r"); + } + } + printf("]"); + printf("\n\r"); + } + } + + /****************************************************************************************** + * opt out Matrix Dimensions Lengths + * ***************************************************************************************/ + void shape(void) + { + if (this->height == 0 || this->channel == 0) + { + printf"%d",width); + printf("\n\r"); + } + else if (this->channel == 0) + { + printf("%d,%d",this->width,this->height) + printf("\n\r"); + } + else + { + printf("%d,%d,%d",this->width,this->height,this->channel); + printf("\n\r"); + } + } + + /****************************************************************************************** + * Calcate Innner Product + * args + * obj : same type matrix. A.dot(B) is AB + * return + * Matrix of innner product matrix + * ***************************************************************************************/ + + Matrix<TYPE> dot(Matrix<TYPE> obj) + { + assert(this->channel == obj.channel); + assert(this->width == obj.height); + //avoid null + assert((0 < this->width && 0 < this->height) || (0 < obj.width && 0 < obj.height)); + + if ((this->height == 0) || (obj.height == 0)) + { + //multiplying condition + assert(this->width == obj.width); + Matrix<TYPE> sum(1); + for (int i = 0; i < width; i++) + { + sum.data[0] = sum.data[0] + this->data[i] * obj.data[i]; + } + return sum; + } + else + { + //multiplying condition + assert((0 < this->width || 0 < this->height) || (0 < obj.width || 0 < obj.height)); + assert(this->width == obj.height); + + Matrix<TYPE> result(obj.width, this->height, this->channel); + + for (int i = 0; i < result.channel; i++) + //channel + { + int channel_offset = (result.width * result.height) * i; + for (int j = 0; j < result.height; j++) + //height + { + int line_offset = j * result.width; + + for (int k = 0; k < result.width; k++) + //width + { + //line inner + TYPE sum = 0.0; + for (int l = 0; l < this->width; l++) + { + int pt_this = l + j * this->width; + int pt_obj = l * obj.width + k; + sum = sum + this->data[pt_this] * obj.data[pt_obj]; + } + // std::cout << channel_offset + line_offset + k << "=" << sum << printf("\n\r"); + result.data[channel_offset + line_offset + k] = sum; + } + } + } + return result; + } + } + + /****************************************************************************************** + * Calcrate self transpose + * return + * transposed Matrix + * ***************************************************************************************/ + Matrix<TYPE> transpose(void) + { + //only 2d array + assertt(channel == 1); + Matrix<TYPE> result(this->height, this->width, this->channel); + for (int h_index = 0; h_index < height; h_index++) + { + for (int w_index = 0; w_index < width; w_index++) + { + result.data[result.calc_pos(h_index, w_index, 0)] = this->data[this->calc_pos(w_index, h_index, 0)]; + } + } + return result; + } + + /****************************************************************************************** + * Aplly argment function to all elements + * return + * Applyed Element Matrix + * ***************************************************************************************/ + Matrix<TYPE> apply(TYPE (*func)(TYPE)) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int i = 0; i < width * height * channel; i++) + { + result.data[i] = func(this->data[i]); + } + return result; + } + + /****************************************************************************************** + * Pic up max value from matrix + * arg + * axis direction of pic up line or face, this data dimention is lower 1 this Matrix + * + * If this matrix's dimention is 1, then,, + * result is 1 element matrix; + * If this matrix's dimention is 2, then... + * if axis is 0, pic up veatrical max value array. + * else if axis is 1, pic up horizonal max value attai, + * If this matrix's dimention is 3 ,then... + * if axis is 0, pic up veatrical max value face. + * else if axis is 1, pic up horizonal max value face. + * else if axis is 2, pic up depth nax value face. + * ***************************************************************************************/ + + Matrix<TYPE> max(int axis) + { + assert(this->width != 0 && this->height != 0 && this->channel != 0); + if ((width == 1 || height == 1) && channel == 1) + { + Matrix<TYPE> result(1, 1, 1); + result.data[0] = this->data[0]; + for (int i = 0; i < (this->width * this->height * this->channel); i++) + { + if (result.data[0] < this->data[i]) + { + result.data[0] = this->data[i]; + } + } + return result; + } + else if (channel == 1) + { + if (axis == 0) + //row direction + { + Matrix<TYPE> result(1, this->height); + for (int y = 0; y < this->height; y++) + { + result.data[result.calc_pos(0, y, 0)] = this->data[calc_pos(0, y, 0)]; + for (int i = 0; i < this->width; i++) + { + if (result.data[result.calc_pos(0, y, 0)] < this->data[calc_pos(i, y, 0)]) + { + result.data[result.calc_pos(0, y, 0)] = this->data[calc_pos(i, y, 0)]; + } + } + } + return result; + } + else if (axis == 1) + //colmn direction + { + Matrix<TYPE> result(this->width, 1); + for (int x = 0; x < this->height; x++) + { + result.data[result.calc_pos(x, 0, 0)] = this->data[calc_pos(x, 0, 0)]; + + for (int i = 0; i < this->height; i++) + { + if (result.data[result.calc_pos(x, 0, 0)] < this->data[calc_pos(x, i, 0)]) + { + result.data[result.calc_pos(x, 0, 0)] = this->data[calc_pos(x, i, 0)]; + } + } + } + return result; + } + } + else if (1 < channel) + { + if (axis == 0) + //row direction + { + Matrix<TYPE> result(1, this->height, this->channel); + for (int y = 0; y < this->height; y++) + { + for (int z = 0; z < this->channel; z++) + { + result.data[result.calc_pos(0, y, z)] = this->data[calc_pos(0, y, z)]; + for (int i = 0; i < this->width; i++) + { + + if (result.data[result.calc_pos(0, y, z)] < this->data[calc_pos(i, y, z)]) + { + result.data[result.calc_pos(0, y, z)] = this->data[calc_pos(i, y, z)]; + } + } + } + } + return result; + } + + else if (axis == 1) + //column direction + { + Matrix<TYPE> result(this->width, 1, this->channel); + for (int x = 0; x < this->height; x++) + { + for (int z = 0; z < this->channel; z++) + { + result.data[result.calc_pos(x, 0, z)] = this->data[calc_pos(x, 0, z)]; + for (int i = 0; i < this->height; i++) + { + + if (result.data[result.calc_pos(x, 0, z)] < this->data[calc_pos(x, i, z)]) + { + result.data[result.calc_pos(x, 0, z)] = this->data[calc_pos(x, i, z)]; + } + } + } + } + return result; + } + else if (axis == 2) + //depth direction + { + Matrix<TYPE> result(this->width, this->height, 1); + + for (int x = 0; x < this->height; x++) + { + for (int y = 0; y < this->channel; y++) + { + result.data[result.calc_pos(x, y, 0)] = this->data[calc_pos(x, y, 0)]; + + for (int i = 0; i < this->channel; i++) + { + + if (result.data[result.calc_pos(x, y, 0)] < this->data[calc_pos(x, y, i)]) + { + result.data[result.calc_pos(x, y, 0)] = this->data[calc_pos(x, y, i)]; + } + } + } + } + return result; + } + } + } + + /****************************************************************************************** + * Pic up index of max value from matrix + * arg + * axis direction of pic up line or face, this data dimention is lower 1 this Matrix + * + * If this matrix's dimention is 1, then,, + * result is 1 element matrix; + * If this matrix's dimention is 2, then... + * if axis is 0, pic up veatrical index array of max values. + * else if axis is 1, pic up horizonal index array of max values, + * If this matrix's dimention is 3 ,then... + * if axis is 0, pic up veatrical index face of max values. + * else if axis is 1, pic up horizonal index face of max values. + * else if axis is 2, pic up depth index face of max values. + * ***************************************************************************************/ + Matrix<TYPE> max_arg(int axis) + { + assert(height != 0 && channel != 0); + if ((width == 0 || height == 0) && channel == 1) + { + Matrix<TYPE> result(1, 1, 1); + Matrix<TYPE> result_index(1, 1, 1); + result.data[0] = this->data[0]; + result_index.data[0] = this->data[0]; + + for (int i = 0; i < (this->width * this->height * this->channel); i++) + { + if (result.data[0] < this->data[i]) + { + result.data[0] = this->data[i]; + result_index.data[0] = (double)i; + } + } + return result_index; + } + else if (channel == 1) + { + if (axis == 0) + //row direction + { + Matrix<TYPE> result(1, this->height); + Matrix<TYPE> result_index(1, this->height); + for (int y = 0; y < this->height; y++) + { + result.data[result.calc_pos(0, y, 0)] = this->data[calc_pos(0, y, 0)]; + result_index.data[result_index.calc_pos(0, y, 0)] = 0; + + for (int i = 0; i < this->width; i++) + { + + if (result.data[result.calc_pos(0, y, 0)] < this->data[calc_pos(i, y, 0)]) + { + result.data[result.calc_pos(0, y, 0)] = this->data[calc_pos(i, y, 0)]; + result_index.data[result_index.calc_pos(0, y, 0)] = (double)i; + } + } + } + return result_index; + } + else if (axis == 1) + //colmn direction + { + Matrix<TYPE> result(this->width, 1); + Matrix<TYPE> result_index(this->width, 1); + for (int x = 0; x < this->height; x++) + { + result.data[result.calc_pos(x, 0, 0)] = this->data[calc_pos(x, 0, 0)]; + result_index.data[result_index.calc_pos(x, 0, 0)] = 0; + for (int i = 0; i < this->height; i++) + { + if (result.data[result.calc_pos(x, 0, 0)] < this->data[calc_pos(x, i, 0)]) + { + result.data[result.calc_pos(x, 0, 0)] = this->data[calc_pos(x, i, 0)]; + result_index.data[result_index.calc_pos(x, 0, 0)] = (double)i; + } + } + } + return result_index; + } + } + else if (1 < channel) + { + if (axis == 0) + //row direction + { + Matrix<TYPE> result(1, this->height, this->channel); + Matrix<TYPE> result_index(1, this->height, this->channel); + for (int y = 0; y < this->height; y++) + { + for (int z = 0; z < this->channel; z++) + { + result.data[result.calc_pos(0, y, z)] = this->data[calc_pos(0, y, z)]; + result_index.data[result_index.calc_pos(0, y, z)] = 0; + + for (int i = 0; i < this->width; i++) + { + + if (result.data[result.calc_pos(0, y, z)] < this->data[calc_pos(i, y, z)]) + { + result.data[result.calc_pos(0, y, z)] = this->data[calc_pos(i, y, z)]; + result_index.data[result_index.calc_pos(0, y, z)] = (double)i; + } + } + } + } + return result_index; + } + + else if (axis == 1) + //column direction + { + Matrix<TYPE> result(this->width, 1, this->channel); + Matrix<TYPE> result_index(this->width, 1, this->channel); + for (int x = 0; x < this->height; x++) + { + for (int z = 0; z < this->channel; z++) + { + result.data[result.calc_pos(x, 0, z)] = this->data[calc_pos(x, 0, z)]; + result_index.data[result_index.calc_pos(x, 0, z)] = 0; + + for (int i = 0; i < this->height; i++) + { + + if (result.data[result.calc_pos(x, 0, z)] < this->data[calc_pos(x, i, z)]) + { + result.data[result.calc_pos(x, 0, z)] = this->data[calc_pos(x, i, z)]; + result_index.data[result_index.calc_pos(x, 0, z)] = (double)i; + } + } + } + } + return result_index; + } + else if (axis == 2) + //depth direction + { + Matrix<TYPE> result(this->width, this->height, 1); + Matrix<TYPE> result_index(this->width, this->height, 1); + + for (int x = 0; x < this->height; x++) + { + for (int y = 0; y < this->channel; y++) + { + result.data[result.calc_pos(x, y, 0)] = this->data[calc_pos(x, y, 0)]; + result_index.data[result_index.calc_pos(x, y, 0)] = 0; + + for (int i = 0; i < this->channel; i++) + { + if (result.data[result.calc_pos(x, y, 0)] < this->data[calc_pos(x, y, i)]) + { + result.data[result.calc_pos(x, y, 0)] = this->data[calc_pos(x, y, i)]; + result_index.data[result_index.calc_pos(x, y, 0)] = (double)i; + } + } + } + } + return result_index; + } + } + } + + /****************************************************************************************** + * Calcrate sum of matrix + * arg + * axis : direction of calcrating sums line or face, this data dimention is lower 1 this Matrix + * + * If this matrix's dimention is 1, then,, + * result is 1 element matrix; + * If this matrix's dimention is 2, then... + * if axis is 0, calcrate veatrical sum array. + * else if axis is 1, calcrate horizonal sum array. + * If this matrix's dimention is 3 ,then... + * if axis is 0, calcrate veatrical sum face. + * else if axis is 1, calcrate horizonal sum face. + * else if axis is 2, calcrate depth sum face. + * ***************************************************************************************/ + + Matrix<TYPE> sum(int axis) + { + assert(height != 0 && channel != 0); + if ((width == 0 || height == 0) && channel == 1) + { + Matrix<TYPE> sum(1, 1, 1); + for (int i = 0; i < (this->width * this->height * this->channel); i++) + { + sum.data[0] = sum.data[0] + this->data[i]; + } + return sum; + } + else if (channel == 1) + { + if (axis == 0) + //row direction + { + Matrix<TYPE> sum(1, this->height); + for (int i = 0; i < this->width; i++) + { + for (int y = 0; y < this->height; y++) + { + sum.data[sum.calc_pos(0, y, 0)] = sum.data[sum.calc_pos(0, y, 0)] + this->data[calc_pos(i, y, 0)]; + } + } + return sum; + } + else if (axis == 1) + //colmn direction + { + Matrix<TYPE> sum(this->width, 1); + for (int i = 0; i < this->height; i++) + { + for (int x = 0; x < this->width; x++) + { + sum.data[sum.calc_pos(x, 0, 0)] = sum.data[sum.calc_pos(x, 0, 0)] + this->data[calc_pos(x, i, 0)]; + } + } + return sum; + } + } + else if (1 < channel) + { + if (axis == 0) + //row direction + { + Matrix<TYPE> sum(1, this->height, this->channel); + for (int i = 0; i < this->width; i++) + { + for (int y = 0; y < this->height; y++) + { + for (int z = 0; z < this->channel; z++) + { + sum.data[sum.calc_pos(0, y, z)] = sum.data[sum.calc_pos(0, y, z)] + this->data[calc_pos(i, y, z)]; + } + } + } + return sum; + } + + else if (axis == 1) + //column direction + { + Matrix<TYPE> sum(this->width, 1, this->channel); + for (int i = 0; i < this->height; i++) + { + for (int x = 0; x < this->height; x++) + { + for (int z = 0; z < this->channel; z++) + { + sum.data[sum.calc_pos(x, 0, z)] = sum.data[sum.calc_pos(x, 0, z)] + this->data[calc_pos(x, i, z)]; + } + } + } + return sum; + } + else if (axis == 2) + //depth direction + { + Matrix<TYPE> sum(this->width, this->height, 1); + + for (int i = 0; i < this->channel; i++) + { + for (int x = 0; x < this->height; x++) + { + for (int y = 0; y < this->channel; y++) + { + sum.data[sum.calc_pos(x, y, 0)] = sum.data[sum.calc_pos(x, y, 0)] + this->data[calc_pos(x, y, i)]; + } + } + } + return sum; + } + } + } + // Operator Over Rodes + + //assign + Matrix<TYPE> operator<<(double x) + { + this->data[this->insert_index] = x; + // std::cout << this->insert_index << ":" << this->data[this->insert_index] << printf("\n\r"); + + this->insert_index = this->insert_index + 1; + return *this; + } + //matrix vs matrix + Matrix<TYPE> operator+(Matrix<TYPE> obj) + { + + if (this->width == obj.width && this->height == obj.height && this->channel == obj.channel) + //simple adder + { + assert(this->width == obj.width && this->height == obj.height && this->channel == obj.channel); + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int i = 0; i < width * height * channel; i++) + { + result.data[i] = this->data[i] + obj.data[i]; + } + return result; + } + //2d vs vector + else if (obj.width != 1 && this->width == obj.width && obj.height == 1 && obj.channel == 1) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] + obj.data[obj.calc_pos(w_index, 0, 0)]; + } + } + } + return result; + } + else if (obj.height != 1 && obj.width == 1 && obj.height == this->height && obj.channel == 1) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] + obj.data[obj.calc_pos(0, h_index, 0)]; + } + } + } + return result; + } + else if (obj.channel != 1 && obj.width == 1 && obj.height == 1 && obj.channel == this->channel) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] + obj.data[obj.calc_pos(0, 0, c_index)]; + } + } + } + return result; + } + //3D vs 2D + else if (this->width == obj.width && obj.height == this->height && obj.channel == 1) + //Z axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] + obj.data[obj.calc_pos(w_index, h_index, 0)]; + } + } + } + return result; + } + else if (this->width == obj.width && obj.height == 1 && obj.channel == this->channel) + //Y axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] + obj.data[obj.calc_pos(w_index, 0, c_index)]; + } + } + } + return result; + } + else if (this->width == 1 && obj.height == 1 && obj.channel == this->channel) + //Z axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] + obj.data[obj.calc_pos(0, h_index, c_index)]; + } + } + } + return result; + } + assert(0); + } + + Matrix<TYPE> operator-(Matrix<TYPE> obj) + { + + assert(this->width == obj.width || this->height == obj.height || this->channel == obj.channel); + + if (this->width == obj.width && this->height == obj.height && this->channel == obj.channel) + //simple adder + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int i = 0; i < width * height * channel; i++) + { + result.data[i] = this->data[i] - obj.data[i]; + } + return result; + } + //2d vs vector + else if (obj.width != 1 && this->width == obj.width && obj.height == 1 && obj.channel == 1) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] - obj.data[obj.calc_pos(w_index, 0, 0)]; + } + } + } + return result; + } + else if (obj.height != 1 && obj.width == 1 && obj.height == this->height && obj.channel == 1) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] - obj.data[obj.calc_pos(0, h_index, 0)]; + } + } + } + return result; + } + else if (obj.channel != 1 && obj.width == 1 && obj.height == 1 && obj.channel == this->channel) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] - obj.data[obj.calc_pos(0, 0, c_index)]; + } + } + } + return result; + } + //3D vs 2D + else if (this->width == obj.width && obj.height == this->height && obj.channel == 1) + //Z axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] - obj.data[obj.calc_pos(w_index, h_index, 0)]; + } + } + } + return result; + } + else if (this->width == obj.width && obj.height == 1 && obj.channel == this->channel) + //Y axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] - obj.data[obj.calc_pos(w_index, 0, c_index)]; + } + } + } + return result; + } + else if (this->width == 1 && obj.height == 1 && obj.channel == this->channel) + //Z axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] - obj.data[obj.calc_pos(0, h_index, c_index)]; + } + } + } + return result; + } + assert(0); + } + + Matrix<TYPE> operator*(Matrix<TYPE> obj) + { + assert(this->width == obj.width || this->height == obj.height || this->channel == obj.channel); + + if (this->width == obj.width && this->height == obj.height && this->channel == obj.channel) + //simple adder + { + assert(this->width == obj.width && this->height == obj.height && this->channel == obj.channel); + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int i = 0; i < width * height * channel; i++) + { + result.data[i] = this->data[i] * obj.data[i]; + } + return result; + } + //2d vs vector + else if (obj.width != 0 && this->width == obj.width && obj.height == 1 && obj.channel == 1) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] * obj.data[obj.calc_pos(w_index, 0, 0)]; + } + } + } + return result; + } + else if (obj.height != 1 && obj.width == 1 && obj.height == this->height && obj.channel == 1) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] * obj.data[obj.calc_pos(0, h_index, 0)]; + } + } + } + return result; + } + else if (obj.channel != 0 && obj.width == 1 && obj.height == 1 && obj.channel == this->channel) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] * obj.data[obj.calc_pos(0, 0, c_index)]; + } + } + } + return result; + } + //3D vs 2D + else if (this->width == obj.width && obj.height == this->height && obj.channel == 1) + //Z axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] * obj.data[obj.calc_pos(w_index, h_index, 0)]; + } + } + } + return result; + } + else if (this->width == obj.width && obj.height == 1 && obj.channel == this->channel) + //Y axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] * obj.data[obj.calc_pos(w_index, 0, c_index)]; + } + } + } + return result; + } + else if (this->width == 1 && obj.height == 1 && obj.channel == this->channel) + //Z axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] * obj.data[obj.calc_pos(0, h_index, c_index)]; + } + } + } + return result; + } + assert(0); + } + + Matrix<TYPE> operator/(Matrix<TYPE> obj) + { + assert(this->width == obj.width || this->height == obj.height || this->channel == obj.channel); + + if (this->width == obj.width && this->height == obj.height && this->channel == obj.channel) + //simple adder + { + assert(this->width == obj.width && this->height == obj.height && this->channel == obj.channel); + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int i = 0; i < width * height * channel; i++) + { + result.data[i] = this->data[i] / obj.data[i]; + } + return result; + } + //2d vs vector + else if (obj.width != 0 && this->width == obj.width && obj.height == 1 && obj.channel == 1) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] / obj.data[obj.calc_pos(w_index, 0, 0)]; + } + } + } + return result; + } + else if (obj.height != 1 && obj.width == 1 && obj.height == this->height && obj.channel == 1) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] / obj.data[obj.calc_pos(0, h_index, 0)]; + } + } + } + return result; + } + else if (obj.channel != 1 && obj.width == 1 && obj.height == 1 && obj.channel == this->channel) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] / obj.data[obj.calc_pos(0, 0, c_index)]; + } + } + } + return result; + } + //3D vs 2D + else if (this->width == obj.width && obj.height == this->height && obj.channel == 1) + //Z axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] / obj.data[obj.calc_pos(w_index, h_index, 0)]; + } + } + } + return result; + } + else if (this->width == obj.width && obj.height == 1 && obj.channel == this->channel) + //Y axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] / obj.data[obj.calc_pos(w_index, 0, c_index)]; + } + } + } + return result; + } + else if (this->width == 1 && obj.height == 1 && obj.channel == this->channel) + //X axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] / obj.data[obj.calc_pos(0, h_index, c_index)]; + } + } + } + return result; + } + assert(0); + } + + Matrix<TYPE> compare(Matrix<TYPE> obj) + { + assert(this->width == obj.width || this->height == obj.height || this->channel == obj.channel); + + if (this->width == obj.width && this->height == obj.height && this->channel == obj.channel) + //simple adder + { + assert(this->width == obj.width && this->height == obj.height && this->channel == obj.channel); + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int i = 0; i < width * height * channel; i++) + { + result.data[i] = (double)(this->data[i] == obj.data[i]); + } + return result; + } + //2d vs vector + else if (obj.width != 0 && this->width == obj.width && obj.height == 1 && obj.channel == 1) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = (double)(this->data[this->calc_pos(w_index, h_index, c_index)] == obj.data[obj.calc_pos(w_index, 0, 0)]); + } + } + } + return result; + } + else if (obj.height != 1 && obj.width == 1 && obj.height == this->height && obj.channel == 1) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = (double)(this->data[this->calc_pos(w_index, h_index, c_index)] == obj.data[obj.calc_pos(0, h_index, 0)]); + } + } + } + return result; + } + else if (obj.channel != 1 && obj.width == 1 && obj.height == 1 && obj.channel == this->channel) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = (double)(this->data[this->calc_pos(w_index, h_index, c_index)] == obj.data[obj.calc_pos(0, 0, c_index)]); + } + } + } + return result; + } + //3D vs 2D + else if (this->width == obj.width && obj.height == this->height && obj.channel == 1) + //Z axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = (double)(this->data[this->calc_pos(w_index, h_index, c_index)] == obj.data[obj.calc_pos(w_index, h_index, 0)]); + } + } + } + return result; + } + else if (this->width == obj.width && obj.height == 1 && obj.channel == this->channel) + //Y axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = (double)(this->data[this->calc_pos(w_index, h_index, c_index)] == obj.data[obj.calc_pos(w_index, 0, c_index)]); + } + } + } + return result; + } + else if (this->width == 1 && obj.height == 1 && obj.channel == this->channel) + //X axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = (double)(this->data[this->calc_pos(w_index, h_index, c_index)] == obj.data[obj.calc_pos(0, h_index, c_index)]); + } + } + } + return result; + } + assert(0); + } + + //matrix vs double + Matrix<TYPE> operator+(double x) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int i = 0; i < width * height * channel; i++) + { + result.data[i] = this->data[i] + x; + } + return result; + } + + Matrix<TYPE> operator*(double x) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int i = 0; i < width * height * channel; i++) + { + result.data[i] = this->data[i] * x; + } + return result; + } + + Matrix<TYPE> operator/(double x) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int i = 0; i < width * height * channel; i++) + { + result.data[i] = this->data[i] / x; + } + return result; + } + + //clone + Matrix<TYPE> clone(void) + { + assert(this->data != NULL); + if (height == 0 || channel == 0) + { + Matrix<TYPE> cloned(this->width); + for (int i = 0; i < width; i++) + { + cloned.data[i] = this->data[i]; + } + return cloned; + } + else + { + Matrix<TYPE> cloned(this->width, this->height, this->channel); + for (int i = 0; i < width * height * channel; i++) + { + cloned.data[i] = this->data[i]; + } + return cloned; + } + //don't copy counter of << + } + + // overwrite by random parameter + Matrix<TYPE> random(double ave, double dis) + { + assert(this->width > 0 && this->height > 0 && this->channel > 0); + Matrix<TYPE> result(this->width, this->height, this->channel); + std::random_device rd{}; + std::mt19937 gen{rd()}; + + std::random_device seed_gen; + std::default_random_engine engine(seed_gen()); + std::normal_distribution<double> dist(ave, dis); + + for (int i = 0; i < width * height * channel; i++) + { + double tmp = (double)dist(engine); + //std::cout << tmp << printf("\n\r"); + + result.data[i] = (tmp + 0.5); + } + return result; + } + /***************************************************************************************************************************************************************************************************************************/ + /***************************************************************************************************************************************************************************************************************************/ + /***************************************************************************************************************************************************************************************************************************/ + /***************************************************************************************************************************************************************************************************************************/ + /***************************************************************************************************************************************************************************************************************************/ + /************************************************************turatan**************************************************************************************************************************************************************/ + /***************************************************************************************************************************************************************************************************************************/ + /***************************************************************************************************************************************************************************************************************************/ + /***************************************************************************************************************************************************************************************************************************/ + /***************************************************************************************************************************************************************************************************************************/ + /***************************************************************************************************************************************************************************************************************************/ + + /****************************************************************************************** + * Calcate Innner Product + * args + * obj : same type matrix. A.dot(B) is AB + * return + * Matrix of innner product matrix + * ***************************************************************************************/ + + Matrix<TYPE> dot(mat::ConstMatrix obj) + { + assert(this->channel == obj.channel); + assert(this->width == obj.height); + //avoid null + assert((0 < this->width && 0 < this->height) || (0 < obj.width && 0 < obj.height)); + + if ((this->height == 0) || (obj.height == 0)) + { + //multiplying condition + assert(this->width == obj.width); + Matrix<TYPE> sum(1); + for (int i = 0; i < width; i++) + { + sum.data[0] = sum.data[0] + this->data[i] * TYPE(obj.data[i]); + } + return sum; + } + else + { + //multiplying condition + assert((0 < this->width || 0 < this->height) || (0 < obj.width || 0 < obj.height)); + assert(this->width == obj.height); + + Matrix<TYPE> result(obj.width, this->height, this->channel); + + for (int i = 0; i < result.channel; i++) + //channel + { + int channel_offset = (result.width * result.height) * i; + for (int j = 0; j < result.height; j++) + //height + { + int line_offset = j * result.width; + + for (int k = 0; k < result.width; k++) + //width + { + //line inner + TYPE sum = 0.0; + for (int l = 0; l < this->width; l++) + { + int pt_this = l + j * this->width; + int pt_obj = l * obj.width + k; + sum = sum + this->data[pt_this] * TYPE(obj.data[pt_obj]); + } + // std::cout << channel_offset + line_offset + k << "=" << sum << printf("\n\r"); + result.data[channel_offset + line_offset + k] = sum; + } + } + } + return result; + } + } + + + /********* + operator**************************************************/ + Matrix<TYPE> operator+(mat::ConstMatrix obj) + { + + if (this->width == obj.width && this->height == obj.height && this->channel == obj.channel) + //simple adder + { + assert(this->width == obj.width && this->height == obj.height && this->channel == obj.channel); + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int i = 0; i < width * height * channel; i++) + { + result.data[i] = this->data[i] + TYPE(obj.data[i]); + } + return result; + } + //2d vs vector + else if (obj.width != 1 && this->width == obj.width && obj.height == 1 && obj.channel == 1) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] + TYPE(obj.data[obj.calc_pos(w_index, 0, 0)]); + } + } + } + return result; + } + else if (obj.height != 1 && obj.width == 1 && obj.height == this->height && obj.channel == 1) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] + TYPE(obj.data[obj.calc_pos(0, h_index, 0)]); + } + } + } + return result; + } + else if (obj.channel != 1 && obj.width == 1 && obj.height == 1 && obj.channel == this->channel) + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] + TYPE(obj.data[obj.calc_pos(0, 0, c_index)]); + } + } + } + return result; + } + //3D vs 2D + else if (this->width == obj.width && obj.height == this->height && obj.channel == 1) + //Z axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] + TYPE(obj.data[obj.calc_pos(w_index, h_index, 0)]); + } + } + } + return result; + } + else if (this->width == obj.width && obj.height == 1 && obj.channel == this->channel) + //Y axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] + TYPE(obj.data[obj.calc_pos(w_index, 0, c_index)]); + } + } + } + return result; + } + else if (this->width == 1 && obj.height == 1 && obj.channel == this->channel) + //Z axis face + { + Matrix<TYPE> result(this->width, this->height, this->channel); + for (int c_index = 0; c_index < this->channel; c_index++) + { + for (int h_index = 0; h_index < this->height; h_index++) + { + for (int w_index = 0; w_index < this->width; w_index++) + { + result.data[this->calc_pos(w_index, h_index, c_index)] = this->data[this->calc_pos(w_index, h_index, c_index)] + TYPE(obj.data[obj.calc_pos(0, h_index, c_index)]); + } + } + } + return result; + } + assert(0); + } +}; + + +} // namespace mat +#endif \ No newline at end of file