#include <iostream>

class Int17Matrix3D {
public:
  Int17Matrix3D(int x, int y, int z) : width_(x), height_(y), depth_(z) {
    array_ = new int32_t[kNumLenght_ * x * y * z];
    std::memset(array_, 0, kNumLenght_ * x * y * z * sizeof(int32_t));
  }

  ~Int17Matrix3D() {
    delete[] array_;
  }

  Int17Matrix3D(const Int17Matrix3D& other) : width_(other.width_), height_(other.height_), depth_(other.depth_) {
    array_ = new int32_t[kNumLenght_ * width_ * height_ * depth_];
    std::memcpy(array_, other.array_, kNumLenght_ * width_ * height_ * depth_ * sizeof(int32_t));
  }

  Int17Matrix3D& operator=(const Int17Matrix3D& other);

  static Int17Matrix3D make_array(int x, int y, int z);

  Int17Matrix3D& operator[](int index);

  int32_t Int17Matrix3D::operator[](int index) const;

  operator int();

  Int17Matrix3D& operator=(int32_t value);

private:
  const int8_t kNumLenght_ = 17;
  int32_t current_index_;
  int32_t max_index_;
  int32_t width_;
  int32_t height_;
  int32_t depth_;
  int32_t* array_;
  int32_t current_x_ = 0;
  int32_t current_y_ = 0;
  int32_t current_z_ = 0;

  bool TakeBit(const int32_t* value, uint32_t bit_position) const;

  Int17Matrix3D& ClearBit(int32_t* value, int32_t bit_position);

  Int17Matrix3D& SetBit(int32_t* value, int32_t bit_position);

  int GetIndex(int x, int y, int z) const;

  int32_t ToDecimal(const int32_t* array_, int32_t current_index_) const;

  friend Int17Matrix3D operator+(const Int17Matrix3D& lhs, const Int17Matrix3D& rhs);

  friend Int17Matrix3D operator-(const Int17Matrix3D& lhs, const Int17Matrix3D& rhs);

  friend Int17Matrix3D operator*(const Int17Matrix3D& lhs, const int32_t& rhs);

  friend std::ostream& operator<<(std::ostream& stream, const Int17Matrix3D& array);

  friend bool operator==(const Int17Matrix3D& lhs, int32_t rhs);

  friend bool operator==(int32_t lhs, const Int17Matrix3D& rhs);

  friend bool operator==(const Int17Matrix3D& lhs, const Int17Matrix3D& rhs);

  friend bool operator!=(const Int17Matrix3D& lhs, const Int17Matrix3D& rhs);
};


#include <iostream>
#include "Int17Matrix3D.h"

Int17Matrix3D& Int17Matrix3D::operator=(const Int17Matrix3D& other) {
  if (this != &other) {
      delete[] array_;
      width_ = other.width_;
      height_ = other.height_;
      depth_ = other.depth_;
      array_ = new int32_t[kNumLenght_ * width_ * height_ * depth_];
      std::memcpy(array_, other.array_, kNumLenght_ * width_ * height_ * depth_ * sizeof(int32_t));
  }
  return *this;
} 

Int17Matrix3D Int17Matrix3D::make_array(int x, int y, int z) {
  return Int17Matrix3D(x, y, z);
}

Int17Matrix3D& Int17Matrix3D::operator[](int index) {
  static int8_t counter = 0;
  if (counter == 0) {
    current_x_ = index;
  } else if (counter == 1) {
    current_y_ = index;
  } else {
    current_z_ = index;
  }

  if (counter == 2) {
    current_index_ = GetIndex(current_x_, current_y_, current_z_);
    counter = -1;
  }

  ++counter;

  if (current_x_ >= width_ || current_y_ >= height_ || current_z_ >= depth_) {
    throw std::out_of_range("Indices are out of bounds"); 
  }

  return *this;
}

int Int17Matrix3D::operator[](int index) const {
  return ToDecimal(array_, current_index_);
}

Int17Matrix3D& Int17Matrix3D::operator=(int32_t value) {
  int first_bit_index = current_index_ * kNumLenght_;

  for (int i = 0; i < kNumLenght_; ++i) {
    if (value & (1 << i)) {
      SetBit(array_, first_bit_index + i);
    } else {
      ClearBit(array_, first_bit_index + i);
    }
  }
  return *this;
}

bool Int17Matrix3D::TakeBit(const int32_t* value, uint32_t bit_position) const {
  int array_index = bit_position / 32;
  int bit_index = bit_position % 32;
  return ((value[array_index] >> bit_index) & 1) != 0;
}

Int17Matrix3D& Int17Matrix3D::ClearBit(int32_t* value, int32_t bit_position) {
  value[bit_position / 32] &= ~(1 << (bit_position % 32));
  return *this;
  }

Int17Matrix3D& Int17Matrix3D::SetBit(int32_t* value, int32_t bit_position) {
  value[bit_position / 32] |= (1 << (bit_position % 32));
  return *this;
}

int Int17Matrix3D::GetIndex(int x, int y, int z) const {
  return x + y * (width_ * kNumLenght_) + z * (width_ * height_ * kNumLenght_);
}

int32_t Int17Matrix3D::ToDecimal(const int32_t* array_, int32_t current_index_) const {
  int first_bit_index = current_index_ * kNumLenght_;
  int32_t decimal_value = 0;
  int32_t exp = 1;

  for (int i = 0; i < kNumLenght_; ++i) {
    if (TakeBit(array_, first_bit_index + i)) {
      decimal_value += exp;
    }
    exp <<= 1;
  }

  return decimal_value;
}

Int17Matrix3D operator+(const Int17Matrix3D& lhs, const Int17Matrix3D& rhs) {
  if (lhs.width_ != rhs.width_ || lhs.height_ != rhs.height_ || lhs.depth_ != rhs.depth_) {
    throw std::out_of_range("Arrays must be with the same size");
  }

  Int17Matrix3D result(lhs.width_, lhs.height_, lhs.depth_);

  for (int z = 0; z < lhs.depth_; ++z) {
    for (int y = 0; y < lhs.height_; ++y) {
      for (int x = 0; x < lhs.width_; ++x) {
        int index = lhs.GetIndex(x, y, z);

        int val_lhs = lhs.ToDecimal(lhs.array_, index);
        int val_rhs = rhs.ToDecimal(rhs.array_, index);

        result[x][y][z] = val_lhs + val_rhs;
      }
    }
  }

  return result;
}

Int17Matrix3D operator-(const Int17Matrix3D& lhs, const Int17Matrix3D& rhs) {
  if (lhs.width_ != rhs.width_ || lhs.height_ != rhs.height_ || lhs.depth_ != rhs.depth_) {
    throw std::out_of_range("Arrays must be with the same size");
  }

  Int17Matrix3D result(lhs.width_, lhs.height_, lhs.depth_);

  for (int z = 0; z < lhs.depth_; ++z) {
    for (int y = 0; y < lhs.height_; ++y) {
      for (int x = 0; x < lhs.width_; ++x) {
        int index = lhs.GetIndex(x, y, z);

        int val_lhs = lhs.ToDecimal(lhs.array_, index);
        int val_rhs = rhs.ToDecimal(rhs.array_, index);

        result[x][y][z] = val_lhs - val_rhs;
      }
    }
  }

  return result;
}

Int17Matrix3D operator*(const Int17Matrix3D& lhs, const int32_t& rhs) {
  Int17Matrix3D result(lhs.width_, lhs.height_, lhs.depth_);

  for (int z = 0; z < lhs.depth_; ++z) {
    for (int y = 0; y < lhs.height_; ++y) {
      for (int x = 0; x < lhs.width_; ++x) {
        int index = lhs.GetIndex(x, y, z);

        int val_lhs = lhs.ToDecimal(lhs.array_, index);

        result[x][y][z] = val_lhs * rhs;
      }
    }
  }

  return result;
}

bool operator==(const Int17Matrix3D& lhs, int32_t rhs) {
  return lhs.ToDecimal(lhs.array_, lhs.current_index_) == rhs;
}

bool operator==(int32_t lhs, const Int17Matrix3D& rhs) {
  return lhs == rhs.ToDecimal(rhs.array_, rhs.current_index_);
}

bool operator==(const Int17Matrix3D& lhs, const Int17Matrix3D& rhs) {
  return lhs.ToDecimal(lhs.array_, lhs.current_index_) == rhs.ToDecimal(rhs.array_, rhs.current_index_);
}

bool operator!=(const Int17Matrix3D& lhs, const Int17Matrix3D& rhs) {
  return !(lhs == rhs);
}

std::ostream& operator<<(std::ostream& stream, const Int17Matrix3D& array) {
  for (int z = 0; z < array.depth_; ++z) {
    for (int y = 0; y < array.height_; ++y) {
      for (int x = 0; x < array.width_; ++x) {
        if (x != 0) {
          stream << " ";
        }
        int temp = array[x][y][z];
        stream << temp;
      }
      stream << '\n'; 
    }
    if (z != array.depth_ - 1) {
      stream << '\n'; 
    }
  }
  return stream;
}


[  7%] Building CXX object lib/CMakeFiles/Int17Matrix3D.dir/Int17Matrix3D.cpp.o
In file included from /Users/alex/labwork5-SPLOIT47/lib/Int17Matrix3D.cpp:2:
/Users/alex/labwork5-SPLOIT47/lib/Int17Matrix3D.h:25:26: error: extra qualification on member 'operator[]'
  int32_t Int17Matrix3D::operator[](int index) const;
          ~~~~~~~~~~~~~~~^
/Users/alex/labwork5-SPLOIT47/lib/Int17Matrix3D.cpp:183:28: error: subscripted value is not an array, pointer, or vector
        int temp = array[x][y][z];
                   ~~~~~~~~^~
2 errors generated.
make[2]: *** [lib/CMakeFiles/Int17Matrix3D.dir/Int17Matrix3D.cpp.o] Error 1
make[1]: *** [lib/CMakeFiles/Int17Matrix3D.dir/all] Error 2
make: *** [all] Error 2


how to fix it without proxi calsse