<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2007-2009 <NAME>
 * Written (W) 2016 <NAME>
 * Copyright (C) 2007-2009 Fraunhofer Institute FIRST and Max-Planck-Society
 */

#include <shogun/lib/common.h>
#include <shogun/distance/EuclideanDistance.h>
#include <shogun/features/Features.h>
#include <shogun/features/DotFeatures.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/mathematics/Math.h>

using namespace shogun;

CEuclideanDistance::CEuclideanDistance() : CDistance()
{
	register_params();
}

CEuclideanDistance::CEuclideanDistance(CDotFeatures* l, CDotFeatures* r) : CDistance()
{
	register_params();
	init(l, r);
}

CEuclideanDistance::~CEuclideanDistance()
{
	cleanup();
}

bool CEuclideanDistance::init(CFeatures* l, CFeatures* r)
{
	cleanup();

	CDistance::init(l, r);
	REQUIRE(l->has_property(FP_DOT), "Left hand side features must support dot property!\n");
	REQUIRE(r->has_property(FP_DOT), "Right hand side features must support dot property!\n");

	CDotFeatures* casted_l=static_cast<CDotFeatures*>(l);
	CDotFeatures* casted_r=static_cast<CDotFeatures*>(r);

	REQUIRE(casted_l->get_dim_feature_space()==casted_r->get_dim_feature_space(),
		"Number of dimension mismatch (l:%d vs. r:%d)!\n",
		casted_l->get_dim_feature_space(),casted_r->get_dim_feature_space());

	precompute_lhs();
	if (lhs==rhs)
		m_rhs_squared_norms=m_lhs_squared_norms;
	else
		precompute_rhs();

	return true;
}

void CEuclideanDistance::cleanup()
{
	reset_precompute();
}

float64_t CEuclideanDistance::compute(int32_t idx_a, int32_t idx_b)
{
	float64_t result=0;
	CDotFeatures* casted_lhs=static_cast<CDotFeatures*>(lhs);
	CDotFeatures* casted_rhs=static_cast<CDotFeatures*>(rhs);

	if (lhs->get_feature_class()==rhs->get_feature_class() || lhs->support_compatible_class())
		result=casted_lhs->dot(idx_a, casted_rhs, idx_b);
	else
		result=casted_rhs->dot(idx_b, casted_lhs, idx_a);

	SG_DEBUG("distance=(%f)+(%f)-2*(%f)\n", m_lhs_squared_norms[idx_a], m_rhs_squared_norms[idx_a], result);

	result=m_lhs_squared_norms[idx_a]+m_rhs_squared_norms[idx_b]-2*result;
	if (disable_sqrt)
		return result;
	return CMath::sqrt(result);
}

void CEuclideanDistance::precompute_lhs()
{
	REQUIRE(lhs, "Left hand side feature cannot be NULL!\n");
	const index_t num_vec=lhs->get_num_vectors();

	if (!m_lhs_squared_norms.vector || m_lhs_squared_norms.vlen!=num_vec)
		m_lhs_squared_norms=SGVector<float64_t>(num_vec);

	CDotFeatures* casted_lhs=static_cast<CDotFeatures*>(lhs);
#pragma omp paralle for
	for(index_t i =0; i<num_vec; ++i)
		m_lhs_squared_norms[i]=casted_lhs->dot(i, casted_lhs, i);
}

void CEuclideanDistance::precompute_rhs()
{
	REQUIRE(rhs, "Right hand side feature cannot be NULL!\n");
	const index_t num_vec=rhs->get_num_vectors();

	if (!m_rhs_squared_norms.vector || m_rhs_squared_norms.vlen!=num_vec)
		m_rhs_squared_norms=SGVector<float64_t>(num_vec);

	CDotFeatures* casted_rhs=static_cast<CDotFeatures*>(rhs);
#pragma omp paralle for
	for(index_t i =0; i<num_vec; ++i)
		m_rhs_squared_norms[i]=casted_rhs->dot(i, casted_rhs, i);
}

void CEuclideanDistance::reset_precompute()
{
	m_lhs_squared_norms=SGVector<float64_t>();<commit_msg>fix uninitialized memory read error in CEuclideanDistance and a typo<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2007-2009 <NAME>
 * Written (W) 2016 <NAME>
 * Copyright (C) 2007-2009 Fraunhofer Institute FIRST and Max-Planck-Society
 */

#include <shogun/lib/common.h>
#include <shogun/distance/EuclideanDistance.h>
#include <shogun/features/Features.h>
#include <shogun/features/DotFeatures.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/mathematics/Math.h>

using namespace shogun;

CEuclideanDistance::CEuclideanDistance() : CDistance()
{
	register_params();
}

CEuclideanDistance::CEuclideanDistance(CDotFeatures* l, CDotFeatures* r) : CDistance()
{
	register_params();
	init(l, r);
}

CEuclideanDistance::~CEuclideanDistance()
{
	cleanup();
}

bool CEuclideanDistance::init(CFeatures* l, CFeatures* r)
{
	cleanup();

	CDistance::init(l, r);
	REQUIRE(l->has_property(FP_DOT), "Left hand side features must support dot property!\n");
	REQUIRE(r->has_property(FP_DOT), "Right hand side features must support dot property!\n");

	CDotFeatures* casted_l=static_cast<CDotFeatures*>(l);
	CDotFeatures* casted_r=static_cast<CDotFeatures*>(r);

	REQUIRE(casted_l->get_dim_feature_space()==casted_r->get_dim_feature_space(),
		"Number of dimension mismatch (l:%d vs. r:%d)!\n",
		casted_l->get_dim_feature_space(),casted_r->get_dim_feature_space());

	precompute_lhs();
	if (lhs==rhs)
		m_rhs_squared_norms=m_lhs_squared_norms;
	else
		precompute_rhs();

	return true;
}

void CEuclideanDistance::cleanup()
{
	reset_precompute();
}

float64_t CEuclideanDistance::compute(int32_t idx_a, int32_t idx_b)
{
	float64_t result=0;
	CDotFeatures* casted_lhs=static_cast<CDotFeatures*>(lhs);
	CDotFeatures* casted_rhs=static_cast<CDotFeatures*>(rhs);

	if (lhs->get_feature_class()==rhs->get_feature_class() || lhs->support_compatible_class())
		result=casted_lhs->dot(idx_a, casted_rhs, idx_b);
	else
		result=casted_rhs->dot(idx_b, casted_lhs, idx_a);

	SG_DEBUG("distance=(%f)+(%f)-2*(%f)\n", m_lhs_squared_norms[idx_a], m_rhs_squared_norms[idx_a], result);

	result=m_lhs_squared_norms[idx_a]+m_rhs_squared_norms[idx_b]-2*result;
	if (disable_sqrt)
		return result;
	return CMath::sqrt(result);
}

void CEuclideanDistance::precompute_lhs()
{
	REQUIRE(lhs, "Left hand side feature cannot be NULL!\n");
	const index_t num_vec=lhs->get_num_vectors();

	if (m_lhs_squared_norms.vlen!=num_vec)
		m_lhs_squared_norms=SGVector<float64_t>(num_vec);

	CDotFeatures* casted_lhs=static_cast<CDotFeatures*>(lhs);
#pragma omp parallel for
	for(index_t i =0; i<num_vec; ++i)
		m_lhs_squared_norms[i]=casted_lhs->dot(i, casted_lhs, i);
}

void CEuclideanDistance::precompute_rhs()
{
	REQUIRE(rhs, "Right hand side feature cannot be NULL!\n");
	const index_t num_vec=rhs->get_num_vectors();

	if (m_rhs_squared_norms.vlen!=num_vec)
		m_rhs_squared_norms=SGVector<float64_t>(num_vec);

	CDotFeatures* casted_rhs=static_cast<CDotFeatures*>(rhs);
#pragma omp parallel for
	for(index_t i =0; i<num_vec; ++i)
		m_rhs_squared_norms[i]=casted_rhs->dot(i, casted_rhs, i);
}

void CEuclideanDistance::reset_precompute()
{
	m_lhs_squared_norms=SGVector<float64_t>();
{'fraction_non_alphanumeric': 0.13622291021671826, 'fraction_numerical': 0.011794191360754828, 'mean_word_length': 7.293398533007335, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 67, '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': '4999986', 'n_tokens_mistral': 2802, 'n_tokens_neox': 2606, 'n_words': 476}