| 362 | } |
| 363 | |
| 364 | static bool GetEmbeddingFeaturesData( |
| 365 | Napi::Env env, |
| 366 | const uint32_t sampleCount, |
| 367 | const Napi::Value& embeddingFeatures, // array or empty |
| 368 | uint32_t* embeddingFeatureCount, |
| 369 | std::vector<size_t>* embeddingDimensions, |
| 370 | std::vector<float>* storage, |
| 371 | std::vector<const float*>* dataPtrsStorage, |
| 372 | std::vector<const float**>* sampleDataPtrs |
| 373 | ) { |
| 374 | embeddingDimensions->clear(); |
| 375 | storage->clear(); |
| 376 | dataPtrsStorage->clear(); |
| 377 | sampleDataPtrs->clear(); |
| 378 | if (embeddingFeatures.IsEmpty()) { |
| 379 | *embeddingFeatureCount = 0; |
| 380 | } else { |
| 381 | const Napi::Array embeddingsFeaturesArray = embeddingFeatures.As<Napi::Array>(); |
| 382 | const uint32_t embeddingFeatureCountLocal = embeddingsFeaturesArray[0u].As<Napi::Array>().Length(); |
| 383 | *embeddingFeatureCount = embeddingFeatureCountLocal; |
| 384 | |
| 385 | embeddingDimensions->reserve(embeddingFeatureCountLocal); |
| 386 | // this is a lower bound, final allocation is delayed until the first sample is processed and |
| 387 | // embedding dimensions become known |
| 388 | storage->reserve(embeddingFeatureCountLocal * sampleCount); |
| 389 | dataPtrsStorage->reserve(embeddingFeatureCountLocal * sampleCount); |
| 390 | |
| 391 | size_t perSampleValuesSize = 0; |
| 392 | |
| 393 | for (uint32_t i = 0; i < sampleCount; ++i) { |
| 394 | const Napi::Array row = embeddingsFeaturesArray[i].As<Napi::Array>(); |
| 395 | for (uint32_t j = 0; j < embeddingFeatureCountLocal; ++j) { |
| 396 | const Napi::Array embeddingValues = row[j].As<Napi::Array>(); |
| 397 | auto embeddingSize = embeddingValues.Length(); |
| 398 | if (i == 0) { |
| 399 | embeddingDimensions->push_back(embeddingSize); |
| 400 | } else { |
| 401 | if (!NHelper::Check( |
| 402 | env, |
| 403 | (*embeddingDimensions)[j] == embeddingSize, |
| 404 | "Embedding values arrays have different lengths" |
| 405 | )) |
| 406 | { |
| 407 | return false; |
| 408 | } |
| 409 | } |
| 410 | |
| 411 | for (uint32_t k = 0; k < embeddingSize; ++k) { |
| 412 | storage->push_back(embeddingValues[k].As<Napi::Number>().FloatValue()); |
| 413 | } |
| 414 | // can't update dataPtrsStorage just yet as it is not reserved to final size |
| 415 | } |
| 416 | if (i == 0) { |
| 417 | perSampleValuesSize = storage->size(); |
| 418 | storage->reserve(perSampleValuesSize * sampleCount); |
| 419 | } |
| 420 | const float* dataPtr = storage->data() + perSampleValuesSize * i; |
| 421 | for (uint32_t j = 0; j < embeddingFeatureCountLocal; ++j) { |
no test coverage detected