| 122 | } |
| 123 | |
| 124 | int Tensor::from_json(const std::string& name, const json& val, void* bytes_ptr, size_t bytes_size) { |
| 125 | this->name = name; |
| 126 | std::string dtype_str = val.value("dtype", ""); |
| 127 | if (auto dtype = string_to_codec_dtype(dtype_str)) { |
| 128 | this->dtype = *dtype; |
| 129 | } else { |
| 130 | std::cerr << "bad dtype" << std::endl; |
| 131 | return -1; |
| 132 | } |
| 133 | size_t dsize = codec_dtype_size(this->dtype); |
| 134 | |
| 135 | size_t numel = 1; |
| 136 | if (val.at("shape").size() > 4) { |
| 137 | std::cerr << "shape exceeds 4 dimensions" << std::endl; |
| 138 | } |
| 139 | for (size_t i = 0; i < val.at("shape").size() && i < 4; i++) { |
| 140 | if (val.at("shape")[i].get<int>() != val.at("shape")[i]) { |
| 141 | std::cerr << "bad shape" << std::endl; |
| 142 | return -1; |
| 143 | } |
| 144 | shape[i] = val.at("shape")[i].get<int>(); |
| 145 | numel *= shape[i]; |
| 146 | } |
| 147 | if (val.at("data_offsets").size() != 2) { |
| 148 | return -1; |
| 149 | } |
| 150 | size_t offset_start = static_cast<size_t>(val.at("data_offsets")[0]); |
| 151 | size_t offset_end = static_cast<size_t>(val.at("data_offsets")[1]); |
| 152 | if (offset_start < 0 || offset_end <= offset_start || offset_end > bytes_size) { |
| 153 | std::cerr << "bad offsets" << std::endl; |
| 154 | return -1; |
| 155 | } |
| 156 | this->data = (char*)bytes_ptr + offset_start; |
| 157 | this->size = offset_end - offset_start; |
| 158 | // validate the shape matches the size |
| 159 | if (numel * dsize != this->size) { |
| 160 | std::cerr << "bad size" << std::endl; |
| 161 | return -1; |
| 162 | } |
| 163 | return 0; |
| 164 | } |
| 165 | |
| 166 | QTensor QTensor::from_codec_tensor(const Tensor& tensor, Quant weight_quant, std::array<int, 4> shape, const int debug_line) { |
| 167 | QTensor qtensor; |
no test coverage detected