using System;
using System.Collections.Generic;
namespace Luneraria.Core
{
///
/// Scalar helpers with the exact semantics of the GDScript built-ins the rules used
/// (clampf, maxf, minf, roundf, floori, ceili, is_equal_approx). Doubles throughout.
///
public static class GdMath
{
public const double CmpEpsilon = 0.00001;
public static double Clamp(double value, double low, double high)
{
return value < low ? low : (value > high ? high : value);
}
public static int Clamp(int value, int low, int high)
{
return value < low ? low : (value > high ? high : value);
}
/// Godot's MAX macro: (a > b) ? a : b.
public static double Max(double a, double b)
{
return a > b ? a : b;
}
/// Godot's MIN macro: (a < b) ? a : b.
public static double Min(double a, double b)
{
return a < b ? a : b;
}
public static int Max(int a, int b) { return a > b ? a : b; }
public static int Min(int a, int b) { return a < b ? a : b; }
public static int FloorI(double value) { return (int)Math.Floor(value); }
public static int CeilI(double value) { return (int)Math.Ceiling(value); }
/// roundf: half away from zero (C round), not banker's rounding.
public static double Round(double value)
{
return Math.Round(value, MidpointRounding.AwayFromZero);
}
public static bool IsEqualApprox(double a, double b)
{
if (a == b)
return true;
double tolerance = CmpEpsilon * Math.Abs(a);
if (tolerance < CmpEpsilon)
tolerance = CmpEpsilon;
return Math.Abs(a - b) < tolerance;
}
/// GDScript atan2(y, x) on doubles.
public static double Atan2(double y, double x) { return Math.Atan2(y, x); }
///
/// Stable insertion sort with a "less than" predicate. Every comparator of the rules is
/// a strict order on distinct unit ids or sequence numbers, so the result is unique;
/// stability keeps it deterministic even for near ties.
///
public static void SortStable(List list, Func less)
{
for (int i = 1; i < list.Count; i++)
{
T item = list[i];
int j = i - 1;
while (j >= 0 && less(item, list[j]))
{
list[j + 1] = list[j];
j--;
}
list[j + 1] = item;
}
}
}
}