<commit_before>package thx.color;

using thx.core.Arrays;
using thx.core.Floats;
import thx.color.parse.ColorParser;
using thx.core.error.NullArgument;

@:access(thx.color.CIELCh)
@:access(thx.color.XYZ)
@:access(thx.color.RGBX)
abstract CIELab(Array<Float>) {
  public var l(get, never) : Float;
  public var a(get, never) : Float;
  public var b(get, never) : Float;

  public static function create(l : Float, a : Float, b : Float)
    return new CIELab([l, a, b]);

  @:from public static function fromFloats(arr : Array<Float>) : CIELab {
    arr.resize(3);
    return CIELab.create(arr[0], arr[1], arr[2]);
  }

  @:from public static function fromString(color : String) : CIELab {
    var info = ColorParser.parseColor(color);
    if(null == info)
      return null;

    return try switch info.name {
      case 'cielab':
        CIELab.fromFloats(ColorParser.getFloatChannels(info.channels, 3, false));
      case _:
        null;
    } catch(e : Dynamic) null;
  }

  inline function new(channels : Array<Float>) : CIELab
    this = channels;

  public function distance(other : CIELab)
    return (l - other.l) * (l - other.l) +
           (a - other.a) * (a - other.a) +
           (b - other.b) * (b - other.b);

  public function interpolate(other : CIELab, t : Float) : CIELab
    return new CIELab([
      t.interpolate(l, other.l),
      t.interpolate(a, other.a),
      t.interpolate(b, other.b)
    ]);

  public function darker(t : Float) : CIELab
    return new CIELab([
      t.interpolate(l, 0),
      a,
      b
    ]);

  public function lighter(t : Float) : CIELab
    return new CIELab([
      t.interpolate(l, 100),
      a,
      b
    ]);

  public function match(palette : Iterable<CIELab>) : CIELab {
    palette.throwIfEmpty();
    var dist = Math.POSITIVE_INFINITY,
        closest = null;
    for(color in palette) {
      var ndist = distance(color);
      if(ndist < dist) {
        dist = ndist;
        closest = color;
      }
    }
    return closest;
  }

  @:op(A==B) public function equals(other : CIELab) : Bool
    return l == other.l && a == other.a && b == other.b;

  public function withLightness(lightness : Float) : CIELab
    return new CIELab([lightness.clamp(0, 100), a, b]);

  public function withA(newa : Float) : CIELab
    return new CIELab([l, newa.clampSym(128), b]);

  public function withB(newb : Float) : CIELab
    return new CIELab([l, a, newb.clampSym(128)]);

  @:to public function toString() : String
    return 'CIELab($l,$a,$b)';

  @:to public function toCIELCh() : CIELCh {
    var h = Floats.wrapCircular(Math.atan2(b, a) * 180 / Math.PI, 360),
        c = Math.sqrt(a * a + b * b);
    return new CIELCh([l, c, h]);
  }<commit_msg>removed boundaries from methods in Lab<commit_after>package thx.color;

using thx.core.Arrays;
using thx.core.Floats;
import thx.color.parse.ColorParser;
using thx.core.error.NullArgument;

@:access(thx.color.CIELCh)
@:access(thx.color.XYZ)
@:access(thx.color.RGBX)
abstract CIELab(Array<Float>) {
  public var l(get, never) : Float;
  public var a(get, never) : Float;
  public var b(get, never) : Float;

  public static function create(l : Float, a : Float, b : Float)
    return new CIELab([l, a, b]);

  @:from public static function fromFloats(arr : Array<Float>) : CIELab {
    arr.resize(3);
    return CIELab.create(arr[0], arr[1], arr[2]);
  }

  @:from public static function fromString(color : String) : CIELab {
    var info = ColorParser.parseColor(color);
    if(null == info)
      return null;

    return try switch info.name {
      case 'cielab':
        CIELab.fromFloats(ColorParser.getFloatChannels(info.channels, 3, false));
      case _:
        null;
    } catch(e : Dynamic) null;
  }

  inline function new(channels : Array<Float>) : CIELab
    this = channels;

  public function distance(other : CIELab)
    return (l - other.l) * (l - other.l) +
           (a - other.a) * (a - other.a) +
           (b - other.b) * (b - other.b);

  public function interpolate(other : CIELab, t : Float) : CIELab
    return new CIELab([
      t.interpolate(l, other.l),
      t.interpolate(a, other.a),
      t.interpolate(b, other.b)
    ]);

  public function darker(t : Float) : CIELab
    return new CIELab([
      t.interpolate(l, 0),
      a,
      b
    ]);

  public function lighter(t : Float) : CIELab
    return new CIELab([
      t.interpolate(l, 100),
      a,
      b
    ]);

  public function match(palette : Iterable<CIELab>) : CIELab {
    palette.throwIfEmpty();
    var dist = Math.POSITIVE_INFINITY,
        closest = null;
    for(color in palette) {
      var ndist = distance(color);
      if(ndist < dist) {
        dist = ndist;
        closest = color;
      }
    }
    return closest;
  }

  @:op(A==B) public function equals(other : CIELab) : Bool
    return l == other.l && a == other.a && b == other.b;

  public function withLightness(lightness : Float) : CIELab
    return new CIELab([lightness, a, b]);

  public function withA(newa : Float) : CIELab
    return new CIELab([l, newa, b]);

  public function withB(newb : Float) : CIELab
    return new CIELab([l, a, newb]);

  @:to public function toString() : String
    return 'CIELab($l,$a,$b)';

  @:to public function toCIELCh() : CIELCh {
    var h = Floats.wrapCircular(Math.atan2(b, a) * 180 / Math.PI, 360),
        c = Math.sqrt(a * a + b * b);
    return new CIELCh([l, c, h]);
  }
{'fraction_non_alphanumeric': 0.1418255878541011, 'fraction_numerical': 0.007776337715237919, 'mean_word_length': 2.767085076708508, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 11, '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': '777739', 'n_tokens_mistral': 2051, 'n_tokens_neox': 1937, 'n_words': 496}