| 722 | } |
| 723 | |
| 724 | JNIEXPORT jstring JNICALL |
| 725 | Java_com_cactus_CactusJNI_nativeIndexQuery(JNIEnv* env, jobject, jlong handle, |
| 726 | jfloatArray embedding, jlong topK, jstring optionsJson) { |
| 727 | if (handle == 0) { throwCactusException(env, "Index not initialized"); return nullptr; } |
| 728 | |
| 729 | jsize embDim = env->GetArrayLength(embedding); |
| 730 | jfloat* embData = env->GetFloatArrayElements(embedding, nullptr); |
| 731 | const char* options = jstring_to_cstr(env, optionsJson); |
| 732 | |
| 733 | std::vector<int> idBuffer(static_cast<size_t>(topK)); |
| 734 | std::vector<float> scoreBuffer(static_cast<size_t>(topK)); |
| 735 | size_t idBufferSize = static_cast<size_t>(topK); |
| 736 | size_t scoreBufferSize = static_cast<size_t>(topK); |
| 737 | |
| 738 | const float* embPtr = embData; |
| 739 | int* idPtr = idBuffer.data(); |
| 740 | float* scorePtr = scoreBuffer.data(); |
| 741 | |
| 742 | int result = cactus_index_query( |
| 743 | reinterpret_cast<cactus_index_t>(handle), |
| 744 | &embPtr, |
| 745 | 1, |
| 746 | static_cast<size_t>(embDim), |
| 747 | options, |
| 748 | &idPtr, |
| 749 | &idBufferSize, |
| 750 | &scorePtr, |
| 751 | &scoreBufferSize |
| 752 | ); |
| 753 | |
| 754 | env->ReleaseFloatArrayElements(embedding, embData, JNI_ABORT); |
| 755 | release_jstring(env, optionsJson, options); |
| 756 | |
| 757 | if (result < 0) { throwOnError(env); return nullptr; } |
| 758 | |
| 759 | std::string json = "{\"results\":["; |
| 760 | for (size_t i = 0; i < idBufferSize; i++) { |
| 761 | if (i > 0) json += ","; |
| 762 | json += "{\"id\":" + std::to_string(idBuffer[i]) + ",\"score\":" + std::to_string(scoreBuffer[i]) + "}"; |
| 763 | } |
| 764 | json += "]}"; |
| 765 | |
| 766 | return env->NewStringUTF(json.c_str()); |
| 767 | } |
| 768 | |
| 769 | JNIEXPORT jint JNICALL |
| 770 | Java_com_cactus_CactusJNI_nativeIndexCompact(JNIEnv* env, jobject, jlong handle) { |
nothing calls this directly
no test coverage detected