scalarOperation

C++ Function Reference

1 Signature

void BigDataStatMeth::DiagonalOps::scalarOperation(BigDataStatMeth::hdf5Dataset *dsInput, BigDataStatMeth::hdf5Dataset *dsResult, double scalar, int operation, std::string target="new", bool bparal=false, Rcpp::Nullable< int > threads=R_NilValue)

2 Description

Perform scalar operations on diagonal elements.

3 Parameters

  • dsInput (BigDataStatMeth::hdf5Dataset *): Input dataset (matrix or vector)
  • dsResult (BigDataStatMeth::hdf5Dataset *): Result dataset (only used if target=“new”)
  • scalar (double): Scalar value for operation
  • operation (int): Operation type: 0=add, 1=subtract, 2=multiply, 3=divide
  • target (std::string): Where to write result: “input”, “new”
  • bparal (bool): Whether to use parallel processing
  • threads (Rcpp::Nullable< int >): Number of threads

4 Details

Applies scalar operations (add, subtract, multiply, divide) to diagonal elements. Automatically detects if input is matrix (extracts diagonal) or vector (direct).

5 Call Graph

Function dependencies

6 Source Code

File: inst/include/hdf5Utilities/hdf5DiagonalMethods.hppLines 612-735

inline void scalarOperation(BigDataStatMeth::hdf5Dataset* dsInput,
                                    BigDataStatMeth::hdf5Dataset* dsResult,
                                    double scalar,
                                    int operation,
                                    std::string target = "new",
                                    bool bparal = false,
                                    Rcpp::Nullable<int> threads = R_NilValue)
        {
            
            try {
                
                H5::Exception::dontPrint();
                
                // BigDataStatMeth::hdf5Dataset* tempInput = nullptr;
                // BigDataStatMeth::hdf5Dataset* tempResult = nullptr;
                std::unique_ptr<BigDataStatMeth::hdf5Dataset> tempInput(nullptr);
                std::unique_ptr<BigDataStatMeth::hdf5Dataset> tempResult(nullptr);

                BigDataStatMeth::hdf5Dataset* finalInput = dsInput;


                bool isVectorInput = isDiagonalVector(dsInput);

                // Extract diagonal from input if it's a matrix
                if (!isVectorInput) {

                    if (dsInput->nrows() != dsInput->ncols()) {
                        throw std::runtime_error("Input matrix must be square for diagonal operations");
                    }

                    std::string tempNameInput = dsInput->getDatasetName() + "_temp_scalar_input";
                    // tempInput = new BigDataStatMeth::hdf5Dataset(dsInput->getFileptr(), dsInput->getGroup(), tempNameInput, true);
                    tempInput.reset(new BigDataStatMeth::hdf5Dataset(dsInput->getFileptr(), dsInput->getGroup(), tempNameInput, true));
                    extractDiagonalToVector(dsInput, tempInput.get());
                    finalInput = tempInput.get();
                }
                
                // Validate input
                hsize_t sizeInput = validateVectorDataset(finalInput);
                if (sizeInput == 0) {
                    throw std::runtime_error("Invalid input dimensions for scalar operation");
                    // cleanup_temp_datasets(tempInput, nullptr);
                    return;
                }
                
                // Determine target for operation result
                BigDataStatMeth::hdf5Dataset* operationTarget = nullptr;

                if (target == "new") {
                    operationTarget = dsResult;
                    // operationTarget->createDataset(1, sizeInput, "real");  // Vector 1×N
                    operationTarget->inheritCompressionLevel(operationTarget->getCompressionLevel());
                    operationTarget->createDataset( sizeInput, 1, "real");  // Vector 1×N
                } else if (target == "input") {
                    if (isVectorInput) {
                        operationTarget = dsInput;  
                    } else {
                        // Para matriz, crear temp y después escribir diagonal
                        std::string tempNameResult = dsInput->getDatasetName() + "_temp_scalar_result";
                        // tempResult = new BigDataStatMeth::hdf5Dataset(dsInput->getFileptr(), dsInput->getGroup(), tempNameResult, true);
                        tempResult.reset(new BigDataStatMeth::hdf5Dataset(dsInput->getFileptr(), dsInput->getGroup(), tempNameResult, true));
                        // tempResult->createDataset(1, sizeInput, "real");
                        tempResult->inheritCompressionLevel(tempResult->getCompressionLevel());
                        tempResult->createDataset(sizeInput, 1, "real"); 
                        operationTarget = tempResult.get();
                    }
                }
                
                // Read input vector data
                std::vector<hsize_t> stride = {1, 1}, block = {1, 1};
                std::vector<double> input_data(sizeInput);
                
                if (finalInput->nrows() == 1) {
                    finalInput->readDatasetBlock({0, 0}, {1, sizeInput}, stride, block, input_data.data());
                } else {
                    finalInput->readDatasetBlock({0, 0}, {sizeInput, 1}, stride, block, input_data.data());
                }
                
                // Apply scalar operation
                if (bparal && sizeInput > 10000) {
                    #pragma omp parallel num_threads(get_threads(bparal, threads))
                    {
                    #pragma omp for schedule(static)
                        for (hsize_t i = 0; i < sizeInput; ++i) {
                            switch (operation) {
                            case 0: input_data[i] += scalar; break;  // add
                            case 1: input_data[i] -= scalar; break;  // subtract
                            case 2: input_data[i] *= scalar; break;  // multiply
                            case 3: input_data[i] /= scalar; break;  // divide
                            case 4: input_data[i] = std::pow(input_data[i], scalar); break;  // power
                            throw std::runtime_error("Unknown scalar operation");
                            }
                        }
                    }
                } else {
                    for (hsize_t i = 0; i < sizeInput; ++i) {
                        switch (operation) {
                        case 0: input_data[i] += scalar; break;
                        case 1: input_data[i] -= scalar; break;
                        case 2: input_data[i] *= scalar; break;
                        case 3: input_data[i] /= scalar; break;
                        case 4: input_data[i] = std::pow(input_data[i], scalar); break;
                        throw std::runtime_error("Unknown scalar operation");
                        }
                    }
                }
                
                // Write result
                operationTarget->writeDatasetBlock(input_data, {0, 0}, {1, sizeInput}, stride, block);
                
                // Write result back to matrix diagonal if needed
                if (target == "input" && !isVectorInput) {
                    writeDiagonalFromVector(tempResult.get(), dsInput);
                }
                
                // Cleanup
                // cleanup_temp_datasets(tempInput, nullptr);
                // if (tempResult) { delete tempResult; tempResult = nullptr; }
            } catch(std::exception& ex) {
                // cleanup_temp_datasets(tempInput, nullptr);
                // if (tempResult) { delete tempResult; tempResult = nullptr; }
                throw std::runtime_error(std::string("Error in scalarOperation: ") + ex.what());
            }
        }

7 Usage Example

#include "BigDataStatMeth.hpp"

// Example usage
auto result = scalarOperation(...);