#include "puzzle_common.h"
#include "puzzle_p.h"
#include "puzzle.h"
#include "globals.h"
int puzzle_vector_sub(PuzzleContext * const context,
PuzzleCvec * const cvecr,
const PuzzleCvec * const cvec1,
const PuzzleCvec * const cvec2,
const int fix_for_texts)
{
size_t remaining;
signed char c1, c2, cr;
(void) context;
if (cvec1->sizeof_vec != cvec2->sizeof_vec ||
cvec1->sizeof_vec <= (size_t) 0U) {
puzzle_err_bug(__FILE__, __LINE__);
}
if (cvecr->vec != NULL) {
puzzle_err_bug(__FILE__, __LINE__);
}
cvecr->sizeof_vec = cvec1->sizeof_vec;
if ((cvecr->vec = calloc(cvecr->sizeof_vec, sizeof *cvecr->vec)) == NULL) {
return -1;
}
remaining = cvec1->sizeof_vec;
if (fix_for_texts != 0) {
do {
remaining--;
c1 = cvec1->vec[remaining];
c2 = cvec2->vec[remaining];
if ((c1 == 0 && c2 == -2) || (c1 == -2 && c2 == 0)) {
cr = -3;
} else if ((c1 == 0 && c2 == +2) || (c1 == +2 && c2 == 0)) {
cr = +3;
} else {
cr = c1 - c2;
}
cvecr->vec[remaining] = cr;
} while (remaining > (size_t) 0U);
} else {
do {
remaining--;
cvecr->vec[remaining] =
cvec1->vec[remaining] - cvec2->vec[remaining];
} while (remaining > (size_t) 0U);
}
return 0;
}
double puzzle_vector_euclidean_length(PuzzleContext * const context,
const PuzzleCvec * const cvec)
{
unsigned long t = 0U;
unsigned long c;
int c2;
size_t remaining;
(void) context;
if ((remaining = cvec->sizeof_vec) <= (size_t) 0U) {
return 0.0;
}
do {
remaining--;
c2 = (int) cvec->vec[remaining];
c = (unsigned long) (c2 * c2);
if (ULONG_MAX - t < c) {
puzzle_err_bug(__FILE__, __LINE__);
}
t += c;
} while (remaining > (size_t) 0U);
return sqrt((double) t);
}
double puzzle_vector_normalized_distance(PuzzleContext * const context,
const PuzzleCvec * const cvec1,
const PuzzleCvec * const cvec2,
const int fix_for_texts)
{
PuzzleCvec cvecr;
double dt, dr;
puzzle_init_cvec(context, &cvecr);
puzzle_vector_sub(context, &cvecr, cvec1, cvec2, fix_for_texts);
dt = puzzle_vector_euclidean_length(context, &cvecr);
puzzle_free_cvec(context, &cvecr);
dr = puzzle_vector_euclidean_length(context, cvec1)
+ puzzle_vector_euclidean_length(context, cvec2);
if (dr == 0.0) {
return 0.0;
}
return dt / dr;
}