src/gliff@internal@similarity.erl

-module(gliff@internal@similarity).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gliff/internal/similarity.gleam").
-export([ratio/1, line_similarity/2]).

-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.

?MODULEDOC(false).

-file("src/gliff/internal/similarity.gleam", 29).
?DOC(false).
-spec lines_of(gliff@types:edit()) -> list(binary()).
lines_of(Edit) ->
    case Edit of
        {equal, Lines} ->
            Lines;

        {insert, Lines@1} ->
            Lines@1;

        {delete, Lines@2} ->
            Lines@2
    end.

-file("src/gliff/internal/similarity.gleam", 15).
?DOC(false).
-spec count(list(gliff@types:edit()), integer(), integer()) -> {integer(),
    integer()}.
count(Edits, Matching, Total) ->
    case Edits of
        [] ->
            {Matching, Total};

        [Edit | Rest] ->
            N = erlang:length(lines_of(Edit)),
            case Edit of
                {equal, _} ->
                    count(Rest, Matching + N, (Total + N) + N);

                {delete, _} ->
                    count(Rest, Matching, Total + N);

                {insert, _} ->
                    count(Rest, Matching, Total + N)
            end
    end.

-file("src/gliff/internal/similarity.gleam", 7).
?DOC(false).
-spec ratio(list(gliff@types:edit())) -> float().
ratio(Edits) ->
    {Matching, Total} = count(Edits, 0, 0),
    case Total of
        0 ->
            1.0;

        _ ->
            case erlang:float(Total) of
                +0.0 -> +0.0;
                -0.0 -> -0.0;
                Gleam@denominator -> erlang:float(2 * Matching) / Gleam@denominator
            end
    end.

-file("src/gliff/internal/similarity.gleam", 51).
?DOC(false).
-spec count_matching_raw(list(gliff@types:raw_edit()), integer()) -> integer().
count_matching_raw(Edits, Acc) ->
    case Edits of
        [] ->
            Acc;

        [{raw_equal, _} | Rest] ->
            count_matching_raw(Rest, Acc + 1);

        [_ | Rest@1] ->
            count_matching_raw(Rest@1, Acc)
    end.

-file("src/gliff/internal/similarity.gleam", 37).
?DOC(false).
-spec line_similarity(binary(), binary()) -> float().
line_similarity(A, B) ->
    A_chars = gleam@string:to_graphemes(A),
    B_chars = gleam@string:to_graphemes(B),
    Total = erlang:length(A_chars) + erlang:length(B_chars),
    case Total of
        0 ->
            1.0;

        _ ->
            Raw_edits = gliff@internal@myers:diff(A_chars, B_chars),
            Matching = count_matching_raw(Raw_edits, 0),
            case erlang:float(Total) of
                +0.0 -> +0.0;
                -0.0 -> -0.0;
                Gleam@denominator -> erlang:float(2 * Matching) / Gleam@denominator
            end
    end.