<commit_before>use {Color, Rgb, Luma, Xyz, Lab, Lch, Hsv, ColorSpace, Mix, Shade, GetHue, Hue, Saturate, RgbHue, clamp};

///Linear HSL color space with an alpha component.
///
///The HSL color space can be seen as a cylindrical version of
///[RGB](struct.Rgb.html), where the `hue` is the angle around the color
///cylinder, the `saturation` is the distance from the center, and the
///`lightness` is the height from the bottom. Its composition makes it
///especially good for operations like changing green to red, making a color
///more gray, or making it darker.
///
///See [HSV](struct.Hsv.html) for a very similar color space, with brightness instead of lightness.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Hsl {
    ///The hue of the color, in degrees. Decides if it's red, blue, purple,
    ///etc.
	pub hue: RgbHue,

    ///The colorfulness of the color. 0.0 gives gray scale colors and 1.0 will
    ///give absolutely clear colors.
	pub saturation: f32,

    ///Decides how light the color will look. 0.0 will be black, 0.5 will give
    ///a clear color, and 1.0 will give white.
	pub lightness: f32,

    ///The transparency of the color. 0.0 is completely transparent and 1.0 is
    ///completely opaque.
	pub alpha: f32,
}

impl Hsl {
    ///Linear HSL.
	pub fn hsl(hue: RgbHue, saturation: f32, lightness: f32) -> Hsl {
		Hsl {
			hue: hue,
			saturation: saturation,
			lightness: lightness,
			alpha: 1.0,
		}
	}

	///Linear HSL and transparency.
	pub fn hsla(hue: RgbHue, saturation: f32, lightness: f32, alpha: f32) -> Hsl {
		Hsl {
			hue: hue,
			saturation: saturation,
			lightness: lightness,
			alpha: alpha,
		}
	}
}

impl ColorSpace for Hsl {
    fn is_valid(&self) -> bool {
        self.saturation >= 0.0 && self.saturation <= 1.0 &&
        self.lightness >= 0.0 && self.lightness <= 1.0 &&
        self.alpha >= 0.0 && self.alpha <= 1.0
    }

    fn clamp(&self) -> Hsl {
        let mut c = *self;
        c.clamp_self();
        c
    }

    fn clamp_self(&mut self) {
        self.saturation = clamp(self.saturation, 0.0, 1.0);
        self.lightness = clamp(self.lightness, 0.0, 1.0);
        self.alpha = clamp(self.alpha, 0.0, 1.0);
    }
}

impl Mix for Hsl {
	fn mix(&self, other: &Hsl, factor: f32) -> Hsl {
        let factor = clamp(factor, 0.0, 1.0);
        let hue_diff: f32 = (other.hue - self.hue).into();

        Hsl {
            hue: self.hue + factor * hue_diff,
            saturation: self.saturation + factor * (other.saturation - self.saturation),
            lightness: self.lightness + factor * (other.lightness - self.lightness),
            alpha: self.alpha + factor * (other.alpha - self.alpha),
        }
    }
}

impl Shade for Hsl {
    fn lighten(&self, amount: f32) -> Hsl {
        Hsl {
            hue: self.hue,
            saturation: self.saturation,
            lightness: self.lightness + amount,
            alpha: self.alpha,
        }
    }
}

impl GetHue for Hsl {
    type Hue = RgbHue;

    fn get_hue(&self) -> Option<RgbHue> {
        if self.saturation <= 0.0 {
            None
        } else {
            Some(self.hue)
        }
    }
}

impl Hue for Hsl {
    fn with_hue(&self, hue: RgbHue) -> Hsl {
        Hsl {
            hue: hue,
            saturation: self.saturation,
            lightness: self.lightness,
            alpha: self.alpha,
        }
    }

    fn shift_hue(&self, amount: RgbHue) -> Hsl {
        Hsl {
            hue: self.hue + amount,
            saturation: self.saturation,
            lightness: self.lightness,
            alpha: self.alpha,
        }
    }
}

impl Saturate for Hsl {
    fn saturate(&self, factor: f32) -> Hsl {
        Hsl {
            hue: self.hue,
            saturation: self.saturation * (1.0 + factor),
            lightness: self.lightness,
            alpha: self.alpha,
        }
    }
}

impl Default for Hsl {
	fn default() -> Hsl {
		Hsl::hsl(0.0.into(), 0.0, 0.0)
	}
}

from_color!(to Hsl from Rgb, Luma, Xyz, Lab, Lch, Hsv);

impl From<Rgb> for Hsl {
	fn from(rgb: Rgb) -> Hsl {
		enum Channel { Red, Green, Blue };

        let val_min = rgb.red.min(rgb.green).min(rgb.blue);
        let mut val_max = rgb.red;
        let mut chan_max = Channel::Red;

        if rgb.green > val_max {
            chan_max = Channel::Green;
            val_max = rgb.green;
        }

        if rgb.blue > val_max {
            chan_max = Channel::Blue;
            val_max = rgb.blue;
        }

        let diff = val_max - val_min;
        let lightness = (val_min + val_max) / 2.0;

        let hue = if diff == 0.0 {<commit_msg>Implement Add and Sub for Hsl<commit_after>use std::ops::{Add, Sub};

use {Color, Rgb, Luma, Xyz, Lab, Lch, Hsv, ColorSpace, Mix, Shade, GetHue, Hue, Saturate, RgbHue, clamp};

///Linear HSL color space with an alpha component.
///
///The HSL color space can be seen as a cylindrical version of
///[RGB](struct.Rgb.html), where the `hue` is the angle around the color
///cylinder, the `saturation` is the distance from the center, and the
///`lightness` is the height from the bottom. Its composition makes it
///especially good for operations like changing green to red, making a color
///more gray, or making it darker.
///
///See [HSV](struct.Hsv.html) for a very similar color space, with brightness instead of lightness.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Hsl {
    ///The hue of the color, in degrees. Decides if it's red, blue, purple,
    ///etc.
	pub hue: RgbHue,

    ///The colorfulness of the color. 0.0 gives gray scale colors and 1.0 will
    ///give absolutely clear colors.
	pub saturation: f32,

    ///Decides how light the color will look. 0.0 will be black, 0.5 will give
    ///a clear color, and 1.0 will give white.
	pub lightness: f32,

    ///The transparency of the color. 0.0 is completely transparent and 1.0 is
    ///completely opaque.
	pub alpha: f32,
}

impl Hsl {
    ///Linear HSL.
	pub fn hsl(hue: RgbHue, saturation: f32, lightness: f32) -> Hsl {
		Hsl {
			hue: hue,
			saturation: saturation,
			lightness: lightness,
			alpha: 1.0,
		}
	}

	///Linear HSL and transparency.
	pub fn hsla(hue: RgbHue, saturation: f32, lightness: f32, alpha: f32) -> Hsl {
		Hsl {
			hue: hue,
			saturation: saturation,
			lightness: lightness,
			alpha: alpha,
		}
	}
}

impl ColorSpace for Hsl {
    fn is_valid(&self) -> bool {
        self.saturation >= 0.0 && self.saturation <= 1.0 &&
        self.lightness >= 0.0 && self.lightness <= 1.0 &&
        self.alpha >= 0.0 && self.alpha <= 1.0
    }

    fn clamp(&self) -> Hsl {
        let mut c = *self;
        c.clamp_self();
        c
    }

    fn clamp_self(&mut self) {
        self.saturation = clamp(self.saturation, 0.0, 1.0);
        self.lightness = clamp(self.lightness, 0.0, 1.0);
        self.alpha = clamp(self.alpha, 0.0, 1.0);
    }
}

impl Mix for Hsl {
	fn mix(&self, other: &Hsl, factor: f32) -> Hsl {
        let factor = clamp(factor, 0.0, 1.0);
        let hue_diff: f32 = (other.hue - self.hue).into();

        Hsl {
            hue: self.hue + factor * hue_diff,
            saturation: self.saturation + factor * (other.saturation - self.saturation),
            lightness: self.lightness + factor * (other.lightness - self.lightness),
            alpha: self.alpha + factor * (other.alpha - self.alpha),
        }
    }
}

impl Shade for Hsl {
    fn lighten(&self, amount: f32) -> Hsl {
        Hsl {
            hue: self.hue,
            saturation: self.saturation,
            lightness: self.lightness + amount,
            alpha: self.alpha,
        }
    }
}

impl GetHue for Hsl {
    type Hue = RgbHue;

    fn get_hue(&self) -> Option<RgbHue> {
        if self.saturation <= 0.0 {
            None
        } else {
            Some(self.hue)
        }
    }
}

impl Hue for Hsl {
    fn with_hue(&self, hue: RgbHue) -> Hsl {
        Hsl {
            hue: hue,
            saturation: self.saturation,
            lightness: self.lightness,
            alpha: self.alpha,
        }
    }

    fn shift_hue(&self, amount: RgbHue) -> Hsl {
        Hsl {
            hue: self.hue + amount,
            saturation: self.saturation,
            lightness: self.lightness,
            alpha: self.alpha,
        }
    }
}

impl Saturate for Hsl {
    fn saturate(&self, factor: f32) -> Hsl {
        Hsl {
            hue: self.hue,
            saturation: self.saturation * (1.0 + factor),
            lightness: self.lightness,
            alpha: self.alpha,
        }
    }
}

impl Default for Hsl {
	fn default() -> Hsl {
		Hsl::hsl(0.0.into(), 0.0, 0.0)
	}
}

impl Add<Hsl> for Hsl {
    type Output = Hsl;

    fn add(self, other: Hsl) -> Hsl {
        Hsl {
            hue: self.hue + other.hue,
            saturation: self.saturation + other.saturation,
            lightness: self.lightness + other.lightness,
            alpha: self.alpha + other.alpha,
        }
    }
}

impl Add<f32> for Hsl {
    type Output = Hsl;

    fn add(self, c: f32) -> Hsl {
        Hsl {
            hue: self.hue + c,
            saturation: self.saturation + c,
            lightness: self.lightness + c,
            alpha: self.alpha + c,
        }
    }
}

impl Sub<Hsl> for Hsl {
    type Output = Hsl;

    fn sub(self, other: Hsl) -> Hsl {
        Hsl {
            hue: self.hue - other.hue,
            saturation: self.saturation - other.saturation,
            lightness: self.lightness - other.lightness,
            alpha: self.alpha - other.alpha,
        }
    }
}

impl Sub<f32> for Hsl {
    type Output = Hsl;

    fn sub(self, c: f32) -> Hsl {
        Hsl {
            hue: self.hue - c,
            saturation: self.saturation - c,
            lightness: self.lightness - c,
            alpha: self.alpha - c,
        }
    }
}

from_color!(to Hsl from Rgb, Luma, Xyz, Lab, Lch, Hsv);

impl From<Rgb> for Hsl {
	fn from(rgb: Rgb) -> Hsl {
		enum Channel { Red, Green, Blue };

        let val_min = rgb.red.min(rgb.green).min(rgb.blue);
        let mut val_max = rgb.red;
        let mut chan_max = Channel::Red;

        if rgb.green > val_max {
            chan_max = Channel::Green;
            val_max = rgb.green;
        }

        if rgb.blue > val_max {
            chan_max = Channel::Blue;
            val_max = rgb.blue;
        }

        let diff = val_max - val_min;
        let lightness = (val_min + val_max) / 2.0;

        let hue = if diff == 0.0 {
{'fraction_non_alphanumeric': 0.12643125180409892, 'fraction_numerical': 0.01654960069277398, 'mean_word_length': 1.879224376731302, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 49, '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': '3037819', 'n_tokens_mistral': 3804, 'n_tokens_neox': 3565, 'n_words': 1056}