<commit_before>/* ----------------------------------------------------------------------- *//**
 *
 * @file linear.cpp
 *
 * @brief Linear-regression functions
 *
 *//* ----------------------------------------------------------------------- */

#include <dbconnector/dbconnector.hpp>
#include <modules/shared/HandleTraits.hpp>
#include <modules/prob/prob.hpp>

namespace madlib {

namespace modules {

// Import names from other MADlib modules
using prob::studentT_CDF;

namespace regress {

// Workaround for Doxygen: Only ignore header file if processed stand-alone
#define MADLIB_REGRESS_LINEAR_CPP
#include "linear.hpp"

/**
 * @brief Transition state for linear-regression functions
 *
 * TransitionState encapsulates the transition state during the
 * linear-regression aggregate functions. To the database, the state is exposed
 * as a single DOUBLE PRECISION array, to the C++ code it is a proper object
 * containing scalars, a vector, and a matrix.
 *
 * Note: We assume that the DOUBLE PRECISION array is initialized by the
 * database with length at least 5, and all elemenets are 0.
 */
template <class Handle, class LinAlgTypes = DefaultLinAlgTypes>
class LinRegrTransitionState : public AbstractionLayer {
    // By §14.5.3/9: "Friend declarations shall not declare partial
    // specializations." We do access protected members in operator+=().
    template <class OtherHandle, class OtherLinAlgTypes>
    friend class LinRegrTransitionState;

public:
    LinRegrTransitionState(const AnyType &inArray)
      : mStorage(inArray.getAs<Handle>()) {
        
        rebind(static_cast<uint16_t>(mStorage[1]));
    }
    
    /**
     * @brief Convert to backend representation
     *
     * We define this function so that we can use TransitionState in the argument
     * list and as a return type.
     */
    inline operator AnyType() const {
        return mStorage;
    }
    
    /**
     * @brief Initialize the transition state. Only called for first row.
     * 
     * @param inAllocator Allocator for the memory transition state. Must fill
     *     the memory block with zeros.
     * @param inWidthOfX Number of independent variables. The first row of data
     *     determines the size of the transition state. This size is a quadratic
     *     function of inWidthOfX.
     */
    inline void initialize(const Allocator &inAllocator, uint16_t inWidthOfX) {
        mStorage = inAllocator.allocateArray<double>(arraySize(inWidthOfX));
        rebind(inWidthOfX);
        widthOfX = inWidthOfX;
    }
    
    /**
     * @brief Merge with another TransitionState object
     */
    template <class OtherHandle>
    LinRegrTransitionState &operator+=(
        const LinRegrTransitionState<OtherHandle, LinAlgTypes> &inOtherState) {
        
        if (mStorage.size() != inOtherState.mStorage.size())
            throw std::logic_error("Internal error: Incompatible transition states");
            
        for (size_t i = 0; i < mStorage.size(); i++)
            mStorage[i] += inOtherState.mStorage[i];
        
        // Undo the addition of widthOfX
        widthOfX = inOtherState.widthOfX;
        return *this;<commit_msg>Linear regression: - Allocate transition state in aggregate context (this saves one copying step after the first call of the transition function)<commit_after>/* ----------------------------------------------------------------------- *//**
 *
 * @file linear.cpp
 *
 * @brief Linear-regression functions
 *
 *//* ----------------------------------------------------------------------- */

#include <dbconnector/dbconnector.hpp>
#include <modules/shared/HandleTraits.hpp>
#include <modules/prob/prob.hpp>

namespace madlib {

namespace modules {

// Import names from other MADlib modules
using prob::studentT_CDF;

namespace regress {

// Workaround for Doxygen: Only ignore header file if processed stand-alone
#define MADLIB_REGRESS_LINEAR_CPP
#include "linear.hpp"

/**
 * @brief Transition state for linear-regression functions
 *
 * TransitionState encapsulates the transition state during the
 * linear-regression aggregate functions. To the database, the state is exposed
 * as a single DOUBLE PRECISION array, to the C++ code it is a proper object
 * containing scalars, a vector, and a matrix.
 *
 * Note: We assume that the DOUBLE PRECISION array is initialized by the
 * database with length at least 5, and all elemenets are 0.
 */
template <class Handle, class LinAlgTypes = DefaultLinAlgTypes>
class LinRegrTransitionState : public AbstractionLayer {
    // By §14.5.3/9: "Friend declarations shall not declare partial
    // specializations." We do access protected members in operator+=().
    template <class OtherHandle, class OtherLinAlgTypes>
    friend class LinRegrTransitionState;

public:
    LinRegrTransitionState(const AnyType &inArray)
      : mStorage(inArray.getAs<Handle>()) {
        
        rebind(static_cast<uint16_t>(mStorage[1]));
    }
    
    /**
     * @brief Convert to backend representation
     *
     * We define this function so that we can use TransitionState in the argument
     * list and as a return type.
     */
    inline operator AnyType() const {
        return mStorage;
    }
    
    /**
     * @brief Initialize the transition state. Only called for first row.
     * 
     * @param inAllocator Allocator for the memory transition state. Must fill
     *     the memory block with zeros.
     * @param inWidthOfX Number of independent variables. The first row of data
     *     determines the size of the transition state. This size is a quadratic
     *     function of inWidthOfX.
     */
    inline void initialize(const Allocator &inAllocator, uint16_t inWidthOfX) {
        mStorage = inAllocator.allocateArray<double, dbal::AggregateContext,
            dbal::DoZero, dbal::ThrowBadAlloc>(arraySize(inWidthOfX));
        rebind(inWidthOfX);
        widthOfX = inWidthOfX;
    }
    
    /**
     * @brief Merge with another TransitionState object
     */
    template <class OtherHandle>
    LinRegrTransitionState &operator+=(
        const LinRegrTransitionState<OtherHandle, LinAlgTypes> &inOtherState) {
        
        if (mStorage.size() != inOtherState.mStorage.size())
            throw std::logic_error("Internal error: Incompatible transition states");
            
        for (size_t i = 0; i < mStorage.size(); i++)
            mStorage[i] += inOtherState.mStorage[i];
        
        // Undo the addition of widthOfX
        widthOfX = inOtherState.widthOfX;
        return *this;
{'fraction_non_alphanumeric': 0.12486594147387774, 'fraction_numerical': 0.003983453347632909, 'mean_word_length': 2.5672131147540984, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4914487', 'n_tokens_mistral': 1770, 'n_tokens_neox': 1728, 'n_words': 588}