diff --git a/icicle/backend/cpu/src/field/cpu_vec_ops.cpp b/icicle/backend/cpu/src/field/cpu_vec_ops.cpp index b2874da68..f279c7b03 100644 --- a/icicle/backend/cpu/src/field/cpu_vec_ops.cpp +++ b/icicle/backend/cpu/src/field/cpu_vec_ops.cpp @@ -46,7 +46,7 @@ enum VecOperation { * Based on the enum value, the functionality is selected and the worker execute that function for every task that * dispatched by the manager. */ -template +template class VectorOpTask : public TaskBase { public: @@ -58,7 +58,7 @@ class VectorOpTask : public TaskBase VecOperation operation, const uint32_t nof_operations, const T* op_a, - const T* op_b, + const U* op_b, const uint32_t stride, T* output) { @@ -202,7 +202,7 @@ class VectorOpTask : public TaskBase void vector_div() { for (uint64_t i = 0; i < m_nof_operations; ++i) { - m_output[i] = m_op_a[i] * T::inverse(m_op_b[i]); + m_output[i] = m_op_a[i] * U::inverse(m_op_b[i]); } } // Single worker functionality to execute conversion from barret to montgomery @@ -354,7 +354,7 @@ class VectorOpTask : public TaskBase VecOperation m_operation; // the operation to execute uint32_t m_nof_operations; // number of operations to execute for this task const T* m_op_a; // pointer to operand A. Operand A is a vector, or matrix in case of replace_elements - const T* m_op_b; // pointer to operand B. Operand B is a vector or scalar + const U* m_op_b; // pointer to operand B. Operand B is a vector or scalar uint64_t m_start_index; // index used in bitreverse operation and out of place matrix transpose uint64_t m_stop_index; // index used in reduce operations and out of place matrix transpose uint32_t m_bit_size; // use in bitrev operation @@ -386,14 +386,14 @@ int get_nof_workers(const VecOpsConfig& config) } // Execute a full task from the type vector = vector (op) vector -template +template eIcicleError -cpu_2vectors_op(VecOperation op, const T* vec_a, const T* vec_b, uint64_t size, const VecOpsConfig& config, T* output) +cpu_2vectors_op(VecOperation op, const T* vec_a, const U* vec_b, uint64_t size, const VecOpsConfig& config, T* output) { - TasksManager> task_manager(get_nof_workers(config) - 1); + TasksManager> task_manager(get_nof_workers(config) - 1); const uint64_t total_nof_operations = size * config.batch_size; for (uint64_t i = 0; i < total_nof_operations; i += NOF_OPERATIONS_PER_TASK) { - VectorOpTask* task_p = task_manager.get_idle_or_completed_task(); + VectorOpTask* task_p = task_manager.get_idle_or_completed_task(); task_p->send_2ops_task( op, std::min((uint64_t)NOF_OPERATIONS_PER_TASK, total_nof_operations - i), vec_a + i, vec_b + i, 1, output + i); } @@ -406,12 +406,12 @@ template eIcicleError cpu_scalar_vector_op( VecOperation op, const T* scalar_a, const T* vec_b, uint64_t size, const VecOpsConfig& config, T* output) { - TasksManager> task_manager(get_nof_workers(config) - 1); + TasksManager> task_manager(get_nof_workers(config) - 1); const uint64_t total_nof_operations = size; const uint32_t stride = config.columns_batch ? config.batch_size : 1; for (uint32_t idx_in_batch = 0; idx_in_batch < config.batch_size; idx_in_batch++) { for (uint64_t i = 0; i < total_nof_operations; i += NOF_OPERATIONS_PER_TASK) { - VectorOpTask* task_p = task_manager.get_idle_or_completed_task(); + VectorOpTask* task_p = task_manager.get_idle_or_completed_task(); task_p->send_2ops_task( op, std::min((uint64_t)NOF_OPERATIONS_PER_TASK, total_nof_operations - i), scalar_a + idx_in_batch, config.columns_batch ? vec_b + idx_in_batch + i * config.batch_size : vec_b + idx_in_batch * size + i, stride, @@ -455,14 +455,14 @@ eIcicleError cpu_vector_sub( REGISTER_VECTOR_SUB_BACKEND("CPU", cpu_vector_sub); /*********************************** MUL ***********************************/ -template +template eIcicleError cpu_vector_mul( - const Device& device, const T* vec_a, const T* vec_b, uint64_t size, const VecOpsConfig& config, T* output) + const Device& device, const T* vec_a, const U* vec_b, uint64_t size, const VecOpsConfig& config, T* output) { return cpu_2vectors_op(VecOperation::VECTOR_MUL, vec_a, vec_b, size, config, output); } -REGISTER_VECTOR_MUL_BACKEND("CPU", cpu_vector_mul); +REGISTER_VECTOR_MUL_BACKEND("CPU", (cpu_vector_mul)); /*********************************** DIV ***********************************/ template @@ -479,10 +479,10 @@ template eIcicleError cpu_convert_montgomery( const Device& device, const T* input, uint64_t size, bool is_to_montgomery, const VecOpsConfig& config, T* output) { - TasksManager> task_manager(get_nof_workers(config) - 1); + TasksManager> task_manager(get_nof_workers(config) - 1); const uint64_t total_nof_operations = size * config.batch_size; for (uint64_t i = 0; i < total_nof_operations; i += NOF_OPERATIONS_PER_TASK) { - VectorOpTask* task_p = task_manager.get_idle_or_completed_task(); + VectorOpTask* task_p = task_manager.get_idle_or_completed_task(); task_p->send_1op_task( (is_to_montgomery ? CONVERT_TO_MONTGOMERY : CONVERT_FROM_MONTGOMERY), std::min((uint64_t)NOF_OPERATIONS_PER_TASK, total_nof_operations - i), input + i, output + i); @@ -499,13 +499,13 @@ REGISTER_CONVERT_MONTGOMERY_BACKEND("CPU", cpu_convert_montgomery); template eIcicleError cpu_vector_sum(const Device& device, const T* vec_a, uint64_t size, const VecOpsConfig& config, T* output) { - TasksManager> task_manager(get_nof_workers(config) - 1); + TasksManager> task_manager(get_nof_workers(config) - 1); std::vector output_initialized = std::vector(config.batch_size, false); uint64_t vec_a_offset = 0; uint64_t idx_in_batch = 0; // run until all vector deployed and all tasks completed while (true) { - VectorOpTask* task_p = + VectorOpTask* task_p = vec_a_offset < size ? task_manager.get_idle_or_completed_task() : task_manager.get_completed_task(); if (task_p == nullptr) { return eIcicleError::SUCCESS; } if (task_p->is_completed()) { @@ -539,13 +539,13 @@ template eIcicleError cpu_vector_product(const Device& device, const T* vec_a, uint64_t size, const VecOpsConfig& config, T* output) { - TasksManager> task_manager(get_nof_workers(config) - 1); + TasksManager> task_manager(get_nof_workers(config) - 1); std::vector output_initialized = std::vector(config.batch_size, false); uint64_t vec_a_offset = 0; uint64_t idx_in_batch = 0; // run until all vector deployed and all tasks completed while (true) { - VectorOpTask* task_p = + VectorOpTask* task_p = vec_a_offset < size ? task_manager.get_idle_or_completed_task() : task_manager.get_completed_task(); if (task_p == nullptr) { return eIcicleError::SUCCESS; } if (task_p->is_completed()) { @@ -610,7 +610,7 @@ template eIcicleError out_of_place_matrix_transpose( const Device& device, const T* mat_in, uint32_t nof_rows, uint32_t nof_cols, const VecOpsConfig& config, T* mat_out) { - TasksManager> task_manager(get_nof_workers(config) - 1); + TasksManager> task_manager(get_nof_workers(config) - 1); uint32_t stride = config.columns_batch ? config.batch_size : 1; const uint64_t total_elements_one_mat = static_cast(nof_rows) * nof_cols; const uint32_t NOF_ROWS_PER_TASK = @@ -620,7 +620,7 @@ eIcicleError out_of_place_matrix_transpose( T* cur_mat_out = config.columns_batch ? mat_out + idx_in_batch : mat_out + idx_in_batch * total_elements_one_mat; // Perform the matrix transpose for (uint32_t i = 0; i < nof_rows; i += NOF_ROWS_PER_TASK) { - VectorOpTask* task_p = task_manager.get_idle_or_completed_task(); + VectorOpTask* task_p = task_manager.get_idle_or_completed_task(); task_p->send_out_of_place_matrix_transpose_task( OUT_OF_PLACE_MATRIX_TRANSPOSE, cur_mat_in + stride * i * nof_cols, std::min((uint64_t)NOF_ROWS_PER_TASK, (uint64_t)nof_rows - i), nof_rows, nof_cols, stride, @@ -695,11 +695,11 @@ eIcicleError matrix_transpose_necklaces( std::vector start_indices_in_mat; // Collect start indices gen_necklace(1, 1, k, length, necklace, start_indices_in_mat); - TasksManager> task_manager(get_nof_workers(config) - 1); + TasksManager> task_manager(get_nof_workers(config) - 1); for (uint64_t i = 0; i < start_indices_in_mat.size(); i += max_nof_operations) { uint64_t nof_operations = std::min((uint64_t)max_nof_operations, start_indices_in_mat.size() - i); for (uint64_t idx_in_batch = 0; idx_in_batch < config.batch_size; idx_in_batch++) { - VectorOpTask* task_p = task_manager.get_idle_or_completed_task(); + VectorOpTask* task_p = task_manager.get_idle_or_completed_task(); task_p->send_replace_elements_task( REPLACE_ELEMENTS, config.columns_batch ? mat_in + idx_in_batch : mat_in + idx_in_batch * total_elements_one_mat, nof_operations, start_indices_in_mat, i, log_nof_rows, log_nof_cols, @@ -746,10 +746,10 @@ cpu_bit_reverse(const Device& device, const T* vec_in, uint64_t size, const VecO ICICLE_ASSERT((1ULL << logn) == size) << "Invalid argument - size is not a power of 2"; // Perform the bit reverse - TasksManager> task_manager(get_nof_workers(config) - 1); + TasksManager> task_manager(get_nof_workers(config) - 1); for (uint64_t idx_in_batch = 0; idx_in_batch < config.batch_size; idx_in_batch++) { for (uint64_t i = 0; i < size; i += NOF_OPERATIONS_PER_TASK) { - VectorOpTask* task_p = task_manager.get_idle_or_completed_task(); + VectorOpTask* task_p = task_manager.get_idle_or_completed_task(); task_p->send_bit_reverse_task( BIT_REVERSE, logn, i, std::min((uint64_t)NOF_OPERATIONS_PER_TASK, size - i), @@ -783,10 +783,10 @@ eIcicleError cpu_slice( ICICLE_ASSERT(vec_in != nullptr && vec_out != nullptr) << "Error: Invalid argument - input or output vector is null"; ICICLE_ASSERT(offset + (size_out - 1) * stride < size_in) << "Error: Invalid argument - slice out of bound"; - TasksManager> task_manager(get_nof_workers(config) - 1); + TasksManager> task_manager(get_nof_workers(config) - 1); for (uint64_t idx_in_batch = 0; idx_in_batch < config.batch_size; idx_in_batch++) { for (uint64_t i = 0; i < size_out; i += NOF_OPERATIONS_PER_TASK) { - VectorOpTask* task_p = task_manager.get_idle_or_completed_task(); + VectorOpTask* task_p = task_manager.get_idle_or_completed_task(); task_p->send_slice_task( SLICE, config.columns_batch ? stride * config.batch_size : stride, config.columns_batch ? config.batch_size : 1, std::min((uint64_t)NOF_OPERATIONS_PER_TASK, size_out - i), @@ -978,7 +978,8 @@ REGISTER_POLYNOMIAL_DIVISION("CPU", cpu_poly_divide); REGISTER_VECTOR_ADD_EXT_FIELD_BACKEND("CPU", cpu_vector_add); REGISTER_VECTOR_ACCUMULATE_EXT_FIELD_BACKEND("CPU", cpu_vector_accumulate); REGISTER_VECTOR_SUB_EXT_FIELD_BACKEND("CPU", cpu_vector_sub); -REGISTER_VECTOR_MUL_EXT_FIELD_BACKEND("CPU", cpu_vector_mul); +REGISTER_VECTOR_MUL_EXT_FIELD_BACKEND("CPU", (cpu_vector_mul)); +REGISTER_VECTOR_MIXED_MUL_BACKEND("CPU", (cpu_vector_mul)); REGISTER_VECTOR_DIV_EXT_FIELD_BACKEND("CPU", cpu_vector_div); REGISTER_CONVERT_MONTGOMERY_EXT_FIELD_BACKEND("CPU", cpu_convert_montgomery); REGISTER_VECTOR_SUM_EXT_FIELD_BACKEND("CPU", cpu_vector_sum); diff --git a/icicle/include/icicle/backend/vec_ops_backend.h b/icicle/include/icicle/backend/vec_ops_backend.h index 2f7cd0638..70fe25102 100644 --- a/icicle/include/icicle/backend/vec_ops_backend.h +++ b/icicle/include/icicle/backend/vec_ops_backend.h @@ -269,20 +269,20 @@ namespace icicle { const VecOpsConfig& config, extension_t* output)>; - using extFieldVectorOpImplInplaceA = std::function; - - using extFieldVectorReduceOpImpl = std::function; - - using extFieldVectorOpImpl = std::function; + using extFieldVectorOpImplInplaceA = std::function; + + using extFieldVectorReduceOpImpl = std::function; + void register_extension_vector_add(const std::string& deviceType, extFieldVectorOpImpl impl); #define REGISTER_VECTOR_ADD_EXT_FIELD_BACKEND(DEVICE_TYPE, FUNC) \ @@ -322,6 +322,16 @@ namespace icicle { }(); \ } + void register_extension_vector_mixed_mul(const std::string& deviceType, mixedVectorOpImpl impl); + + #define REGISTER_VECTOR_MIXED_MUL_BACKEND(DEVICE_TYPE, FUNC) \ + namespace { \ + static bool UNIQUE(_reg_vec_mixed_mul) = []() -> bool { \ + register_extension_vector_mixed_mul(DEVICE_TYPE, FUNC); \ + return true; \ + }(); \ + } + void register_extension_vector_div(const std::string& deviceType, extFieldVectorOpImpl impl); #define REGISTER_VECTOR_DIV_EXT_FIELD_BACKEND(DEVICE_TYPE, FUNC) \ diff --git a/icicle/include/icicle/vec_ops.h b/icicle/include/icicle/vec_ops.h index 115e18667..80785ebae 100644 --- a/icicle/include/icicle/vec_ops.h +++ b/icicle/include/icicle/vec_ops.h @@ -135,6 +135,26 @@ namespace icicle { template eIcicleError vector_mul(const T* vec_a, const T* vec_b, uint64_t size, const VecOpsConfig& config, T* output); + /** + * @brief Multiplies two vectors element-wise. + * + * @tparam T Type of the elements in the vectors. + * @param vec_a Pointer to the first input vector(s). + * - If `config.batch_size > 1`, this should be a concatenated array of vectors. + * - The layout depends on `config.columns_batch`: + * - If `false`, vectors are stored contiguously in memory. + * - If `true`, vectors are stored as columns in a 2D array. + * @param vec_b Pointer to the second input vector(s). + * - The storage layout should match that of `vec_a`. + * @param size Number of elements in each vector. + * @param config Configuration for the operation. + * @param output Pointer to the output vector(s) where the results will be stored. + * The output array should have the same storage layout as the input vectors. + * @return eIcicleError Error code indicating success or failure. + */ + template + eIcicleError vector_mul(const T* vec_a, const U* vec_b, uint64_t size, const VecOpsConfig& config, T* output); + /** * @brief Divides vector `a` by vector `b` element-wise. * diff --git a/icicle/src/vec_ops.cpp b/icicle/src/vec_ops.cpp index acf89190e..e86204469 100644 --- a/icicle/src/vec_ops.cpp +++ b/icicle/src/vec_ops.cpp @@ -194,6 +194,21 @@ namespace icicle { { return CONCAT_EXPAND(FIELD, extension_vector_mul)(vec_a, vec_b, size, &config, output); } + + ICICLE_DISPATCHER_INST(VectorMixedMulDispatcher, extension_vector_mixed_mul, mixedVectorOpImpl); + + extern "C" eIcicleError CONCAT_EXPAND(FIELD, extension_vector_mixed_mul)( + const extension_t* vec_a, const scalar_t* vec_b, uint64_t size, const VecOpsConfig* config, extension_t* output) + { + return VectorMixedMulDispatcher::execute(vec_a, vec_b, size, *config, output); + } + + template <> + eIcicleError vector_mul( + const extension_t* vec_a, const scalar_t* vec_b, uint64_t size, const VecOpsConfig& config, extension_t* output) + { + return CONCAT_EXPAND(FIELD, extension_vector_mixed_mul)(vec_a, vec_b, size, &config, output); + } #endif // EXT_FIELD /*********************************** DIV ***********************************/ diff --git a/wrappers/golang/fields/babybear/extension/vecOps/include/vec_ops.h b/wrappers/golang/fields/babybear/extension/vecOps/include/vec_ops.h index b9029ea7e..0763f0ef9 100644 --- a/wrappers/golang/fields/babybear/extension/vecOps/include/vec_ops.h +++ b/wrappers/golang/fields/babybear/extension/vecOps/include/vec_ops.h @@ -43,6 +43,14 @@ int babybear_extension_matrix_transpose( scalar_t* mat_out ); +int babybear_extension_vector_mixed_mul( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + #ifdef __cplusplus } #endif diff --git a/wrappers/golang/fields/babybear/extension/vecOps/vec_ops.go b/wrappers/golang/fields/babybear/extension/vecOps/vec_ops.go index 1cc914ead..dfea02ac6 100644 --- a/wrappers/golang/fields/babybear/extension/vecOps/vec_ops.go +++ b/wrappers/golang/fields/babybear/extension/vecOps/vec_ops.go @@ -42,3 +42,20 @@ func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, co err := (C.babybear_extension_matrix_transpose(cIn, cRowSize, cColumnSize, cConfig, cOut)) return runtime.EIcicleError(err) } + +func MixedVecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret runtime.EIcicleError) { + aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config) + + cA := (*C.scalar_t)(aPointer) + cB := (*C.scalar_t)(bPointer) + cOut := (*C.scalar_t)(outPointer) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cSize := (C.int)(size) + + switch op { + case core.Mul: + ret = (runtime.EIcicleError)(C.babybear_extension_vector_mixed_mul(cA, cB, cSize, cConfig, cOut)) + } + + return ret +} diff --git a/wrappers/golang/fields/babybear/tests/extension_vec_ops_test.go b/wrappers/golang/fields/babybear/tests/extension_vec_ops_test.go index 4c4cba7cd..df1ffae32 100644 --- a/wrappers/golang/fields/babybear/tests/extension_vec_ops_test.go +++ b/wrappers/golang/fields/babybear/tests/extension_vec_ops_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/core" + babybear "github.com/ingonyama-zk/icicle/v3/wrappers/golang/fields/babybear" babybear_extension "github.com/ingonyama-zk/icicle/v3/wrappers/golang/fields/babybear/extension" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/fields/babybear/extension/vecOps" "github.com/stretchr/testify/suite" @@ -64,6 +65,23 @@ func testBabybear_extensionTranspose(suite *suite.Suite) { suite.Equal(matrix, output) } +func testBabybear_extensionMixedVecOps(suite *suite.Suite) { + testSize := 1 << 14 + + a := babybear_extension.GenerateScalars(testSize) + var scalar babybear.ScalarField + scalar.One() + ones := core.HostSliceWithValue(scalar, testSize) + + out := make(core.HostSlice[babybear_extension.ExtensionField], testSize) + + cfg := core.DefaultVecOpsConfig() + + vecOps.MixedVecOp(a, ones, out, cfg, core.Mul) + + suite.Equal(a, out) +} + type Babybear_extensionVecOpsTestSuite struct { suite.Suite } @@ -71,6 +89,7 @@ type Babybear_extensionVecOpsTestSuite struct { func (s *Babybear_extensionVecOpsTestSuite) TestBabybear_extensionVecOps() { s.Run("TestBabybear_extensionVecOps", testWrapper(&s.Suite, testBabybear_extensionVecOps)) s.Run("TestBabybear_extensionTranspose", testWrapper(&s.Suite, testBabybear_extensionTranspose)) + s.Run("TestBabybear_extensionMixedVecOps", testWrapper(&s.Suite, testBabybear_extensionMixedVecOps)) } func TestSuiteBabybear_extensionVecOps(t *testing.T) { diff --git a/wrappers/golang/fields/babybear/tests/vec_ops_test.go b/wrappers/golang/fields/babybear/tests/vec_ops_test.go index 693fea507..da840237a 100644 --- a/wrappers/golang/fields/babybear/tests/vec_ops_test.go +++ b/wrappers/golang/fields/babybear/tests/vec_ops_test.go @@ -71,6 +71,7 @@ type BabybearVecOpsTestSuite struct { func (s *BabybearVecOpsTestSuite) TestBabybearVecOps() { s.Run("TestBabybearVecOps", testWrapper(&s.Suite, testBabybearVecOps)) s.Run("TestBabybearTranspose", testWrapper(&s.Suite, testBabybearTranspose)) + } func TestSuiteBabybearVecOps(t *testing.T) { diff --git a/wrappers/golang/fields/koalabear/extension/extension_field.go b/wrappers/golang/fields/koalabear/extension/extension_field.go index ace523293..99179c787 100644 --- a/wrappers/golang/fields/koalabear/extension/extension_field.go +++ b/wrappers/golang/fields/koalabear/extension/extension_field.go @@ -168,6 +168,18 @@ func (f ExtensionField) Sqr() ExtensionField { return res } +func (f ExtensionField) Pow(exp int) ExtensionField { + var res ExtensionField + + cF := (*C.scalar_t)(unsafe.Pointer(&f)) + cExp := (C.int)(exp) + cRes := (*C.scalar_t)(unsafe.Pointer(&res)) + + C.koalabear_extension_pow(cF, cExp, cRes) + + return res +} + func convertScalarsMontgomery(scalars core.HostOrDeviceSlice, isInto bool) runtime.EIcicleError { defaultCfg := core.DefaultVecOpsConfig() cValues, _, _, cCfg, cSize := core.VecOpCheck(scalars, scalars, scalars, &defaultCfg) diff --git a/wrappers/golang/fields/koalabear/extension/include/scalar_field.h b/wrappers/golang/fields/koalabear/extension/include/scalar_field.h index deb60836f..6dacf730a 100644 --- a/wrappers/golang/fields/koalabear/extension/include/scalar_field.h +++ b/wrappers/golang/fields/koalabear/extension/include/scalar_field.h @@ -16,6 +16,7 @@ void koalabear_extension_add(const scalar_t* a, const scalar_t* b, scalar_t* res void koalabear_extension_sub(const scalar_t* a, const scalar_t* b, scalar_t* result); void koalabear_extension_mul(const scalar_t* a, const scalar_t* b, scalar_t* result); void koalabear_extension_inv(const scalar_t* a, scalar_t* result); +void koalabear_extension_pow(const scalar_t* a, int exp, scalar_t* result); #ifdef __cplusplus } diff --git a/wrappers/golang/fields/koalabear/extension/vecOps/include/vec_ops.h b/wrappers/golang/fields/koalabear/extension/vecOps/include/vec_ops.h index b5beb8a1f..2fcfd8b10 100644 --- a/wrappers/golang/fields/koalabear/extension/vecOps/include/vec_ops.h +++ b/wrappers/golang/fields/koalabear/extension/vecOps/include/vec_ops.h @@ -43,6 +43,14 @@ int koalabear_extension_matrix_transpose( scalar_t* mat_out ); +int koalabear_extension_vector_mixed_mul( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); + #ifdef __cplusplus } #endif diff --git a/wrappers/golang/fields/koalabear/extension/vecOps/vec_ops.go b/wrappers/golang/fields/koalabear/extension/vecOps/vec_ops.go index 9262574e6..09fa50db7 100644 --- a/wrappers/golang/fields/koalabear/extension/vecOps/vec_ops.go +++ b/wrappers/golang/fields/koalabear/extension/vecOps/vec_ops.go @@ -42,3 +42,20 @@ func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, co err := (C.koalabear_extension_matrix_transpose(cIn, cRowSize, cColumnSize, cConfig, cOut)) return runtime.EIcicleError(err) } + +func MixedVecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret runtime.EIcicleError) { + aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config) + + cA := (*C.scalar_t)(aPointer) + cB := (*C.scalar_t)(bPointer) + cOut := (*C.scalar_t)(outPointer) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cSize := (C.int)(size) + + switch op { + case core.Mul: + ret = (runtime.EIcicleError)(C.koalabear_extension_vector_mixed_mul(cA, cB, cSize, cConfig, cOut)) + } + + return ret +} diff --git a/wrappers/golang/fields/koalabear/include/scalar_field.h b/wrappers/golang/fields/koalabear/include/scalar_field.h index 97facd63a..a91c3d1bd 100644 --- a/wrappers/golang/fields/koalabear/include/scalar_field.h +++ b/wrappers/golang/fields/koalabear/include/scalar_field.h @@ -16,6 +16,7 @@ void koalabear_add(const scalar_t* a, const scalar_t* b, scalar_t* result); void koalabear_sub(const scalar_t* a, const scalar_t* b, scalar_t* result); void koalabear_mul(const scalar_t* a, const scalar_t* b, scalar_t* result); void koalabear_inv(const scalar_t* a, scalar_t* result); +void koalabear_pow(const scalar_t* a, int exp, scalar_t* result); #ifdef __cplusplus } diff --git a/wrappers/golang/fields/koalabear/scalar_field.go b/wrappers/golang/fields/koalabear/scalar_field.go index fb8f37669..da94167f3 100644 --- a/wrappers/golang/fields/koalabear/scalar_field.go +++ b/wrappers/golang/fields/koalabear/scalar_field.go @@ -168,6 +168,18 @@ func (f ScalarField) Sqr() ScalarField { return res } +func (f ScalarField) Pow(exp int) ScalarField { + var res ScalarField + + cF := (*C.scalar_t)(unsafe.Pointer(&f)) + cExp := (C.int)(exp) + cRes := (*C.scalar_t)(unsafe.Pointer(&res)) + + C.koalabear_pow(cF, cExp, cRes) + + return res +} + func convertScalarsMontgomery(scalars core.HostOrDeviceSlice, isInto bool) runtime.EIcicleError { defaultCfg := core.DefaultVecOpsConfig() cValues, _, _, cCfg, cSize := core.VecOpCheck(scalars, scalars, scalars, &defaultCfg) diff --git a/wrappers/golang/fields/koalabear/tests/extension_field_test.go b/wrappers/golang/fields/koalabear/tests/extension_field_test.go index c63f02e81..a6216cee0 100644 --- a/wrappers/golang/fields/koalabear/tests/extension_field_test.go +++ b/wrappers/golang/fields/koalabear/tests/extension_field_test.go @@ -119,6 +119,11 @@ func testExtensionFieldArithmetic(suite *suite.Suite) { suite.Equal(square, mul, "Square and multiplication do not yield the same value") + pow4 := scalarA.Pow(4) + mulBySelf := mul.Mul(&mul) + + suite.Equal(pow4, mulBySelf, "Square and multiplication do not yield the same value") + inv := scalarA.Inv() one := scalarA.Mul(&inv) diff --git a/wrappers/golang/fields/koalabear/tests/extension_vec_ops_test.go b/wrappers/golang/fields/koalabear/tests/extension_vec_ops_test.go index 757e5de0a..582f45b5f 100644 --- a/wrappers/golang/fields/koalabear/tests/extension_vec_ops_test.go +++ b/wrappers/golang/fields/koalabear/tests/extension_vec_ops_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/core" + koalabear "github.com/ingonyama-zk/icicle/v3/wrappers/golang/fields/koalabear" koalabear_extension "github.com/ingonyama-zk/icicle/v3/wrappers/golang/fields/koalabear/extension" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/fields/koalabear/extension/vecOps" "github.com/stretchr/testify/suite" @@ -64,6 +65,23 @@ func testKoalabear_extensionTranspose(suite *suite.Suite) { suite.Equal(matrix, output) } +func testKoalabear_extensionMixedVecOps(suite *suite.Suite) { + testSize := 1 << 14 + + a := koalabear_extension.GenerateScalars(testSize) + var scalar koalabear.ScalarField + scalar.One() + ones := core.HostSliceWithValue(scalar, testSize) + + out := make(core.HostSlice[koalabear_extension.ExtensionField], testSize) + + cfg := core.DefaultVecOpsConfig() + + vecOps.MixedVecOp(a, ones, out, cfg, core.Mul) + + suite.Equal(a, out) +} + type Koalabear_extensionVecOpsTestSuite struct { suite.Suite } @@ -71,6 +89,7 @@ type Koalabear_extensionVecOpsTestSuite struct { func (s *Koalabear_extensionVecOpsTestSuite) TestKoalabear_extensionVecOps() { s.Run("TestKoalabear_extensionVecOps", testWrapper(&s.Suite, testKoalabear_extensionVecOps)) s.Run("TestKoalabear_extensionTranspose", testWrapper(&s.Suite, testKoalabear_extensionTranspose)) + s.Run("TestKoalabear_extensionMixedVecOps", testWrapper(&s.Suite, testKoalabear_extensionMixedVecOps)) } func TestSuiteKoalabear_extensionVecOps(t *testing.T) { diff --git a/wrappers/golang/fields/koalabear/tests/scalar_field_test.go b/wrappers/golang/fields/koalabear/tests/scalar_field_test.go index adb41022f..abbe8d775 100644 --- a/wrappers/golang/fields/koalabear/tests/scalar_field_test.go +++ b/wrappers/golang/fields/koalabear/tests/scalar_field_test.go @@ -119,6 +119,11 @@ func testScalarFieldArithmetic(suite *suite.Suite) { suite.Equal(square, mul, "Square and multiplication do not yield the same value") + pow4 := scalarA.Pow(4) + mulBySelf := mul.Mul(&mul) + + suite.Equal(pow4, mulBySelf, "Square and multiplication do not yield the same value") + inv := scalarA.Inv() one := scalarA.Mul(&inv) diff --git a/wrappers/golang/internal/generator/main.go b/wrappers/golang/internal/generator/main.go index 70428daac..0dc55504f 100644 --- a/wrappers/golang/internal/generator/main.go +++ b/wrappers/golang/internal/generator/main.go @@ -30,7 +30,7 @@ func generateFiles() { fields.Generate(curveDir, curve.PackageName, curve.Curve, scalarFieldPrefix, true, curve.ScalarFieldNumLimbs) fields.Generate(curveDir, curve.PackageName, curve.Curve, "Base", false, curve.BaseFieldNumLimbs) curves.Generate(curveDir, curve.PackageName, curve.Curve, "") - vecops.Generate(curveDir, curve.Curve, scalarFieldPrefix) + vecops.Generate(curveDir, curveDir, curve.Curve, scalarFieldPrefix, curve.Curve) lib_linker.Generate(curveDir, curve.PackageName, curve.Curve, lib_linker.CURVE, 0) @@ -66,7 +66,7 @@ func generateFiles() { fieldDir := path.Join("fields", field.PackageName) scalarFieldPrefix := "Scalar" fields.Generate(fieldDir, field.PackageName, field.Field, scalarFieldPrefix, true, field.LimbsNum) - vecops.Generate(fieldDir, field.Field, scalarFieldPrefix) + vecops.Generate(fieldDir, fieldDir, field.Field, scalarFieldPrefix, field.Field) if field.SupportsNTT { ntt.Generate(fieldDir, "", field.Field, scalarFieldPrefix, field.GnarkImport, field.ROU, true, "", "") poly.Generate(fieldDir, field.Field, scalarFieldPrefix, field.GnarkImport) @@ -78,7 +78,7 @@ func generateFiles() { extensionField := field.Field + "_extension" extensionFieldPrefix := "Extension" fields.Generate(extensionsDir, "extension", extensionField, extensionFieldPrefix, true, field.ExtensionLimbsNum) - vecops.Generate(extensionsDir, extensionField, extensionFieldPrefix) + vecops.Generate(extensionsDir, fieldDir, extensionField, extensionFieldPrefix, field.Field) ntt.Generate(fieldDir, "extension", field.Field, scalarFieldPrefix, field.GnarkImport, field.ROU, false, extensionField, extensionFieldPrefix) } diff --git a/wrappers/golang/internal/generator/vecOps/generate.go b/wrappers/golang/internal/generator/vecOps/generate.go index 66f4fc2ff..48467ca6a 100644 --- a/wrappers/golang/internal/generator/vecOps/generate.go +++ b/wrappers/golang/internal/generator/vecOps/generate.go @@ -12,17 +12,21 @@ var vecOpsTemplates = map[string]string{ "header": "vecOps/templates/vec_ops.h.tmpl", } -func Generate(baseDir, field, fieldPrefix string) { +func Generate(baseDir, secondDir, field, fieldPrefix string, secondField string) { data := struct { - PackageName string - Field string - FieldPrefix string - BaseImportPath string + PackageName string + Field string + FieldPrefix string + BaseImportPath string + SecondField string + SecondImportPath string }{ "vecOps", field, fieldPrefix, baseDir, + secondField, + secondDir, } testDir := "tests" diff --git a/wrappers/golang/internal/generator/vecOps/templates/vec_ops.go.tmpl b/wrappers/golang/internal/generator/vecOps/templates/vec_ops.go.tmpl index e65a5445d..a1456c109 100644 --- a/wrappers/golang/internal/generator/vecOps/templates/vec_ops.go.tmpl +++ b/wrappers/golang/internal/generator/vecOps/templates/vec_ops.go.tmpl @@ -43,3 +43,21 @@ func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, co return runtime.EIcicleError(err) } +{{if eq .FieldPrefix "Extension"}} +func MixedVecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret runtime.EIcicleError) { + aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config) + + cA := (*C.scalar_t)(aPointer) + cB := (*C.scalar_t)(bPointer) + cOut := (*C.scalar_t)(outPointer) + cConfig := (*C.VecOpsConfig)(cfgPointer) + cSize := (C.int)(size) + + switch op { + case core.Mul: + ret = (runtime.EIcicleError)(C.{{.Field}}_vector_mixed_mul(cA, cB, cSize, cConfig, cOut)) + } + + return ret +} +{{end}} \ No newline at end of file diff --git a/wrappers/golang/internal/generator/vecOps/templates/vec_ops.h.tmpl b/wrappers/golang/internal/generator/vecOps/templates/vec_ops.h.tmpl index c4dad5266..96d63981f 100644 --- a/wrappers/golang/internal/generator/vecOps/templates/vec_ops.h.tmpl +++ b/wrappers/golang/internal/generator/vecOps/templates/vec_ops.h.tmpl @@ -42,7 +42,15 @@ int {{.Field}}_matrix_transpose( VecOpsConfig* config, scalar_t* mat_out ); - +{{ if eq .FieldPrefix "Extension" }} +int {{.Field}}_vector_mixed_mul( + scalar_t* vec_a, + scalar_t* vec_b, + int n, + VecOpsConfig* config, + scalar_t* result +); +{{end}} #ifdef __cplusplus } #endif diff --git a/wrappers/golang/internal/generator/vecOps/templates/vec_ops_test.go.tmpl b/wrappers/golang/internal/generator/vecOps/templates/vec_ops_test.go.tmpl index 1bee38471..dc7c28abd 100644 --- a/wrappers/golang/internal/generator/vecOps/templates/vec_ops_test.go.tmpl +++ b/wrappers/golang/internal/generator/vecOps/templates/vec_ops_test.go.tmpl @@ -3,8 +3,9 @@ package tests import ( "testing" - {{.Field}} "github.com/ingonyama-zk/icicle/v3/wrappers/golang/{{.BaseImportPath}}" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/core" + {{.Field}} "github.com/ingonyama-zk/icicle/v3/wrappers/golang/{{.BaseImportPath}}" + {{if eq .FieldPrefix "Extension"}}{{.SecondField}} "github.com/ingonyama-zk/icicle/v3/wrappers/golang/{{.SecondImportPath}}"{{end}} "github.com/ingonyama-zk/icicle/v3/wrappers/golang/{{.BaseImportPath}}/vecOps" "github.com/stretchr/testify/suite" ) @@ -64,6 +65,25 @@ func test{{capitalize .Field}}Transpose(suite *suite.Suite) { suite.Equal(matrix, output) } +{{if eq .FieldPrefix "Extension"}} +func test{{capitalize .Field}}MixedVecOps(suite *suite.Suite) { + testSize := 1 << 14 + + a := {{.Field}}.GenerateScalars(testSize) + var scalar {{.SecondField}}.ScalarField + scalar.One() + ones := core.HostSliceWithValue(scalar, testSize) + + out := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], testSize) + + cfg := core.DefaultVecOpsConfig() + + vecOps.MixedVecOp(a, ones, out, cfg, core.Mul) + + suite.Equal(a, out) +} +{{end}} + type {{capitalize .Field}}VecOpsTestSuite struct { suite.Suite } @@ -71,6 +91,7 @@ type {{capitalize .Field}}VecOpsTestSuite struct { func (s *{{capitalize .Field}}VecOpsTestSuite) Test{{capitalize .Field}}VecOps() { s.Run("Test{{capitalize .Field}}VecOps", testWrapper(&s.Suite, test{{capitalize .Field}}VecOps)) s.Run("Test{{capitalize .Field}}Transpose", testWrapper(&s.Suite, test{{capitalize .Field}}Transpose)) + {{if eq .FieldPrefix "Extension"}}s.Run("Test{{capitalize .Field}}MixedVecOps", testWrapper(&s.Suite, test{{capitalize .Field}}MixedVecOps)){{end}} } func TestSuite{{capitalize .Field}}VecOps(t *testing.T) { diff --git a/wrappers/rust/icicle-core/src/tests.rs b/wrappers/rust/icicle-core/src/tests.rs index 7a18d9297..5d5a8fbcd 100644 --- a/wrappers/rust/icicle-core/src/tests.rs +++ b/wrappers/rust/icicle-core/src/tests.rs @@ -30,13 +30,13 @@ where let result2 = result1 - scalars_b[i]; assert_eq!(result2, scalars_a[i]); } - + // Test field multiplication API let scalar_a = scalars_a[0]; let square = scalar_a.sqr(); let mul_by_self = scalar_a.mul(scalar_a); assert_eq!(square, mul_by_self); - + // Test field pow API let pow_4 = scalar_a.pow(4); let mul_mul = mul_by_self.mul(mul_by_self); diff --git a/wrappers/rust/icicle-core/src/vec_ops/mod.rs b/wrappers/rust/icicle-core/src/vec_ops/mod.rs index 8eb2068cf..e0f5ebea0 100644 --- a/wrappers/rust/icicle-core/src/vec_ops/mod.rs +++ b/wrappers/rust/icicle-core/src/vec_ops/mod.rs @@ -132,9 +132,19 @@ pub trait VecOps { ) -> Result<(), eIcicleError>; } -fn check_vec_ops_args<'a, F>( +#[doc(hidden)] +pub trait MixedVecOps { + fn mul( + a: &(impl HostOrDeviceSlice + ?Sized), + b: &(impl HostOrDeviceSlice + ?Sized), + result: &mut (impl HostOrDeviceSlice + ?Sized), + cfg: &VecOpsConfig, + ) -> Result<(), eIcicleError>; +} + +fn check_vec_ops_args<'a, F, T>( a: &(impl HostOrDeviceSlice + ?Sized), - b: &(impl HostOrDeviceSlice + ?Sized), + b: &(impl HostOrDeviceSlice + ?Sized), result: &(impl HostOrDeviceSlice + ?Sized), cfg: &VecOpsConfig, ) -> VecOpsConfig { @@ -220,6 +230,20 @@ where <::Config as VecOps>::mul(a, b, result, &cfg) } +pub fn mixed_mul_scalars( + a: &(impl HostOrDeviceSlice + ?Sized), + b: &(impl HostOrDeviceSlice + ?Sized), + result: &mut (impl HostOrDeviceSlice + ?Sized), + cfg: &VecOpsConfig, +) -> Result<(), eIcicleError> +where + F: FieldImpl, + ::Config: MixedVecOps, +{ + let cfg = check_vec_ops_args(a, b, result, cfg); + <::Config as MixedVecOps>::mul(a, b, result, &cfg) +} + pub fn div_scalars( a: &(impl HostOrDeviceSlice + ?Sized), b: &(impl HostOrDeviceSlice + ?Sized), @@ -243,7 +267,7 @@ where F: FieldImpl, ::Config: VecOps, { - let cfg = check_vec_ops_args(a, a, result, cfg); //TODO: emirsoyturk + let cfg = check_vec_ops_args(a, a, result, cfg); <::Config as VecOps>::sum(a, result, &cfg) } @@ -256,7 +280,7 @@ where F: FieldImpl, ::Config: VecOps, { - let cfg = check_vec_ops_args(a, a, result, cfg); //TODO: emirsoyturk + let cfg = check_vec_ops_args(a, a, result, cfg); <::Config as VecOps>::product(a, result, &cfg) } @@ -270,7 +294,7 @@ where F: FieldImpl, ::Config: VecOps, { - let cfg = check_vec_ops_args(b, b, result, cfg); //TODO: emirsoyturk + let cfg = check_vec_ops_args(b, b, result, cfg); <::Config as VecOps>::scalar_add(a, b, result, &cfg) } @@ -284,7 +308,7 @@ where F: FieldImpl, ::Config: VecOps, { - let cfg = check_vec_ops_args(b, b, result, cfg); //TODO: emirsoyturk + let cfg = check_vec_ops_args(b, b, result, cfg); <::Config as VecOps>::scalar_sub(a, b, result, &cfg) } @@ -298,7 +322,7 @@ where F: FieldImpl, ::Config: VecOps, { - let cfg = check_vec_ops_args(b, b, result, cfg); //TODO: emirsoyturk + let cfg = check_vec_ops_args(b, b, result, cfg); <::Config as VecOps>::scalar_mul(a, b, result, &cfg) } @@ -740,6 +764,55 @@ macro_rules! impl_vec_ops_field { }; } +#[macro_export] +macro_rules! impl_vec_ops_mixed_field { + ( + $field_prefix:literal, + $field_prefix_ident:ident, + $ext_field:ident, + $field:ident, + $ext_field_config:ident + ) => { + mod $field_prefix_ident { + + use crate::vec_ops::{$ext_field, $field, HostOrDeviceSlice}; + use icicle_core::vec_ops::VecOpsConfig; + use icicle_runtime::errors::eIcicleError; + + extern "C" { + #[link_name = concat!($field_prefix, "_vector_mixed_mul")] + pub(crate) fn vector_mul_ffi( + a: *const $ext_field, + b: *const $field, + size: u32, + cfg: *const VecOpsConfig, + result: *mut $ext_field, + ) -> eIcicleError; + } + } + + impl MixedVecOps<$ext_field, $field> for $ext_field_config { + fn mul( + a: &(impl HostOrDeviceSlice<$ext_field> + ?Sized), + b: &(impl HostOrDeviceSlice<$field> + ?Sized), + result: &mut (impl HostOrDeviceSlice<$ext_field> + ?Sized), + cfg: &VecOpsConfig, + ) -> Result<(), eIcicleError> { + unsafe { + $field_prefix_ident::vector_mul_ffi( + a.as_ptr(), + b.as_ptr(), + a.len() as u32, + cfg as *const VecOpsConfig, + result.as_mut_ptr(), + ) + .wrap() + } + } + } + }; +} + #[macro_export] macro_rules! impl_vec_ops_tests { ( @@ -788,3 +861,29 @@ macro_rules! impl_vec_ops_tests { } }; } + +#[macro_export] +macro_rules! impl_mixed_vec_ops_tests { + ( + $ext_field:ident, + $field:ident + ) => { + pub(crate) mod test_mixed_vecops { + use super::*; + use icicle_runtime::test_utilities; + use icicle_runtime::{device::Device, runtime}; + use std::sync::Once; + + fn initialize() { + test_utilities::test_load_and_init_devices(); + test_utilities::test_set_main_device(); + } + + #[test] + pub fn test_mixed_vec_ops_scalars() { + initialize(); + check_mixed_vec_ops_scalars::<$ext_field, $field>() + } + } + }; +} diff --git a/wrappers/rust/icicle-core/src/vec_ops/tests.rs b/wrappers/rust/icicle-core/src/vec_ops/tests.rs index 14554d284..fd0cfecef 100644 --- a/wrappers/rust/icicle-core/src/vec_ops/tests.rs +++ b/wrappers/rust/icicle-core/src/vec_ops/tests.rs @@ -1,9 +1,9 @@ #![allow(unused_imports)] use crate::traits::GenerateRandom; use crate::vec_ops::{ - accumulate_scalars, add_scalars, bit_reverse, bit_reverse_inplace, div_scalars, mul_scalars, product_scalars, - scalar_add, scalar_mul, scalar_sub, slice, sub_scalars, sum_scalars, transpose_matrix, FieldImpl, VecOps, - VecOpsConfig, + accumulate_scalars, add_scalars, bit_reverse, bit_reverse_inplace, div_scalars, mixed_mul_scalars, mul_scalars, + product_scalars, scalar_add, scalar_mul, scalar_sub, slice, sub_scalars, sum_scalars, transpose_matrix, FieldImpl, + MixedVecOps, VecOps, VecOpsConfig, }; use icicle_runtime::device::Device; use icicle_runtime::memory::{DeviceVec, HostSlice}; @@ -50,6 +50,17 @@ where check_vec_ops_scalars_accumulate::(test_size); } +pub fn check_mixed_vec_ops_scalars() +where + ::Config: MixedVecOps, + ::Config: GenerateRandom, + ::Config: GenerateRandom, +{ + let test_size = 1 << 14; + + check_vec_ops_mixed_scalars_mul::(test_size); +} + pub fn check_vec_ops_scalars_add(test_size: usize) where ::Config: VecOps + GenerateRandom, @@ -436,3 +447,29 @@ where .unwrap(); assert_eq!(input.as_slice(), result_host.as_slice()); } + +pub fn check_vec_ops_mixed_scalars_mul(test_size: usize) +where + ::Config: MixedVecOps + GenerateRandom, + ::Config: GenerateRandom, +{ + let a_main = F::Config::generate_random(test_size); + let b = T::Config::generate_random(test_size); + let mut result_main = vec![F::zero(); test_size]; + let mut result_ref = vec![F::zero(); test_size]; + + let a_main = HostSlice::from_slice(&a_main); + let b = HostSlice::from_slice(&b); + let result_main = HostSlice::from_mut_slice(&mut result_main); + let result_ref = HostSlice::from_mut_slice(&mut result_ref); + + let cfg = VecOpsConfig::default(); + + test_utilities::test_set_main_device(); + mixed_mul_scalars(a_main, b, result_main, &cfg).unwrap(); + + test_utilities::test_set_ref_device(); + mixed_mul_scalars(a_main, b, result_ref, &cfg).unwrap(); + + assert_eq!(result_main.as_slice(), result_ref.as_slice()); +} diff --git a/wrappers/rust/icicle-fields/icicle-babybear/src/vec_ops/mod.rs b/wrappers/rust/icicle-fields/icicle-babybear/src/vec_ops/mod.rs index 3950819dd..6d6794a6a 100644 --- a/wrappers/rust/icicle-fields/icicle-babybear/src/vec_ops/mod.rs +++ b/wrappers/rust/icicle-fields/icicle-babybear/src/vec_ops/mod.rs @@ -1,18 +1,25 @@ use crate::field::{ExtensionCfg, ExtensionField, ScalarCfg, ScalarField}; -use icicle_core::impl_vec_ops_field; -use icicle_core::vec_ops::{VecOps, VecOpsConfig}; +use icicle_core::vec_ops::{MixedVecOps, VecOps, VecOpsConfig}; +use icicle_core::{impl_vec_ops_field, impl_vec_ops_mixed_field}; use icicle_runtime::errors::eIcicleError; use icicle_runtime::memory::HostOrDeviceSlice; impl_vec_ops_field!("babybear", babybear, ScalarField, ScalarCfg); impl_vec_ops_field!("babybear_extension", babybear_extension, ExtensionField, ExtensionCfg); +impl_vec_ops_mixed_field!( + "babybear_extension", + babybear_mixed, + ExtensionField, + ScalarField, + ExtensionCfg +); #[cfg(test)] pub(crate) mod tests { use crate::field::{ExtensionField, ScalarField}; - use icicle_core::impl_vec_ops_tests; use icicle_core::vec_ops::tests::*; + use icicle_core::{impl_mixed_vec_ops_tests, impl_vec_ops_tests}; impl_vec_ops_tests!(ScalarField); @@ -20,5 +27,6 @@ pub(crate) mod tests { use super::*; impl_vec_ops_tests!(ExtensionField); + impl_mixed_vec_ops_tests!(ExtensionField, ScalarField); } } diff --git a/wrappers/rust/icicle-fields/icicle-koalabear/src/vec_ops/mod.rs b/wrappers/rust/icicle-fields/icicle-koalabear/src/vec_ops/mod.rs index cb6667e63..2a1762f7a 100644 --- a/wrappers/rust/icicle-fields/icicle-koalabear/src/vec_ops/mod.rs +++ b/wrappers/rust/icicle-fields/icicle-koalabear/src/vec_ops/mod.rs @@ -1,18 +1,25 @@ use crate::field::{ExtensionCfg, ExtensionField, ScalarCfg, ScalarField}; -use icicle_core::impl_vec_ops_field; -use icicle_core::vec_ops::{VecOps, VecOpsConfig}; +use icicle_core::vec_ops::{MixedVecOps, VecOps, VecOpsConfig}; +use icicle_core::{impl_vec_ops_field, impl_vec_ops_mixed_field}; use icicle_runtime::errors::eIcicleError; use icicle_runtime::memory::HostOrDeviceSlice; impl_vec_ops_field!("koalabear", koalabear, ScalarField, ScalarCfg); impl_vec_ops_field!("koalabear_extension", koalabear_extension, ExtensionField, ExtensionCfg); +impl_vec_ops_mixed_field!( + "koalabear_extension", + koalabear_mixed, + ExtensionField, + ScalarField, + ExtensionCfg +); #[cfg(test)] pub(crate) mod tests { use crate::field::{ExtensionField, ScalarField}; - use icicle_core::impl_vec_ops_tests; use icicle_core::vec_ops::tests::*; + use icicle_core::{impl_mixed_vec_ops_tests, impl_vec_ops_tests}; impl_vec_ops_tests!(ScalarField); @@ -20,5 +27,6 @@ pub(crate) mod tests { use super::*; impl_vec_ops_tests!(ExtensionField); + impl_mixed_vec_ops_tests!(ExtensionField, ScalarField); } } diff --git a/wrappers/rust/icicle-fields/icicle-m31/src/vec_ops/mod.rs b/wrappers/rust/icicle-fields/icicle-m31/src/vec_ops/mod.rs index ee7cca460..552e4c2fa 100644 --- a/wrappers/rust/icicle-fields/icicle-m31/src/vec_ops/mod.rs +++ b/wrappers/rust/icicle-fields/icicle-m31/src/vec_ops/mod.rs @@ -1,18 +1,19 @@ use crate::field::{ExtensionCfg, ExtensionField, ScalarCfg, ScalarField}; -use icicle_core::impl_vec_ops_field; -use icicle_core::vec_ops::{VecOps, VecOpsConfig}; +use icicle_core::vec_ops::{MixedVecOps, VecOps, VecOpsConfig}; +use icicle_core::{impl_vec_ops_field, impl_vec_ops_mixed_field}; use icicle_runtime::errors::eIcicleError; use icicle_runtime::memory::HostOrDeviceSlice; impl_vec_ops_field!("m31", m31, ScalarField, ScalarCfg); impl_vec_ops_field!("m31_extension", m31_extension, ExtensionField, ExtensionCfg); +impl_vec_ops_mixed_field!("m31_extension", m31_mixed, ExtensionField, ScalarField, ExtensionCfg); #[cfg(test)] pub(crate) mod tests { use crate::field::{ExtensionField, ScalarField}; - use icicle_core::impl_vec_ops_tests; use icicle_core::vec_ops::tests::*; + use icicle_core::{impl_mixed_vec_ops_tests, impl_vec_ops_tests}; impl_vec_ops_tests!(ScalarField); @@ -20,5 +21,6 @@ pub(crate) mod tests { use super::*; impl_vec_ops_tests!(ExtensionField); + impl_mixed_vec_ops_tests!(ExtensionField, ScalarField); } }