lib: add color function collection
This commit is contained in:
		
							parent
							
								
									3773a25ef1
								
							
						
					
					
						commit
						9d5fcc0668
					
				
					 6 changed files with 512 additions and 1 deletions
				
			
		
							
								
								
									
										65
									
								
								outputs/lib/color/check.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								outputs/lib/color/check.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,65 @@ | ||||||
|  | {lib, ...}: let | ||||||
|  |   inherit (lib) toInt all min max; | ||||||
|  |   inherit (builtins) isInt isFloat match getAttr hasAttr; | ||||||
|  | 
 | ||||||
|  |   # basic checks | ||||||
|  |   range = a: b: v: (v <= max a b) && (v >= min a b); | ||||||
|  |   number = v: isInt v || isFloat v; | ||||||
|  |   unary = range 0.0 1.0; | ||||||
|  |   hue = range 0.0 360.0; | ||||||
|  | 
 | ||||||
|  |   # type checking | ||||||
|  |   hex = { | ||||||
|  |     string = color: let | ||||||
|  |       hexPatternWithHash = match "#[[:xdigit:]]{6}" color; | ||||||
|  |       hexPatternNoHash = match "[[:xdigit:]]{6}" color; | ||||||
|  |       isValid = hexPatternWithHash != null || hexPatternNoHash != null; | ||||||
|  |     in | ||||||
|  |       assert isValid || throw "Invalid hex color format: ${color}"; | ||||||
|  |         hexPatternWithHash != null || hexPatternNoHash != null; | ||||||
|  |     set = color: let | ||||||
|  |       hasAttributes = all (k: hasAttr k color) ["r" "g" "b"]; | ||||||
|  |       validPattern = all (k: let | ||||||
|  |         v = getAttr k color; | ||||||
|  |       in | ||||||
|  |         match "[[:xdigit:]]{2}" v != null) ["r" "g" "b"]; | ||||||
|  |     in | ||||||
|  |       hasAttributes && validPattern; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   rgb = { | ||||||
|  |     string = color: let | ||||||
|  |       rgbPattern = match "([0-9]{1,3}),([0-9]{1,3}),([0-9]{1,3})" color; | ||||||
|  |       toNum = str: let | ||||||
|  |         num = toInt str; | ||||||
|  |       in | ||||||
|  |         num != null && range 0 255 num; | ||||||
|  |       isValid = rgbPattern != null && all toNum rgbPattern; | ||||||
|  |     in | ||||||
|  |       isValid; | ||||||
|  |     set = color: let | ||||||
|  |       hasAttributes = all (k: hasAttr k color) ["r" "g" "b"]; | ||||||
|  |       validRanges = all ( | ||||||
|  |         k: let | ||||||
|  |           v = getAttr k color; | ||||||
|  |         in | ||||||
|  |           number v && range 0 255 v | ||||||
|  |       ) ["r" "g" "b"]; | ||||||
|  |     in | ||||||
|  |       hasAttributes && validRanges; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   hsl = { | ||||||
|  |     # TODO: add range checks | ||||||
|  |     string = color: let | ||||||
|  |       hslPattern = match "([0-9]{1,3}),[ ]*([0-9]{1,3})%,[ ]*([0-9]{1,3})%" color; | ||||||
|  |     in | ||||||
|  |       hslPattern != null; | ||||||
|  | 
 | ||||||
|  |     set = color: let | ||||||
|  |       hasAttributes = all (k: hasAttr k color) ["h" "s" "l"]; | ||||||
|  |       validRanges = hue color.h && all (k: unary (getAttr k color)) ["s" "l"]; | ||||||
|  |     in | ||||||
|  |       hasAttributes && validRanges; | ||||||
|  |   }; | ||||||
|  | in {inherit range number unary hue hex rgb hsl;} | ||||||
							
								
								
									
										207
									
								
								outputs/lib/color/translate.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								outputs/lib/color/translate.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,207 @@ | ||||||
|  | { | ||||||
|  |   math, | ||||||
|  |   types, | ||||||
|  |   lib, | ||||||
|  | }: let | ||||||
|  |   inherit (builtins) substring; | ||||||
|  |   inherit (lib) min max; | ||||||
|  |   hex = { | ||||||
|  |     toSet = string: | ||||||
|  |       types.hex.set { | ||||||
|  |         r = substring 0 2 string; | ||||||
|  |         g = substring 2 2 string; | ||||||
|  |         b = substring 4 2 string; | ||||||
|  |       }; | ||||||
|  |     toRGB = let | ||||||
|  |       dictionary = { | ||||||
|  |         "0" = 0; | ||||||
|  |         "1" = 1; | ||||||
|  |         "2" = 2; | ||||||
|  |         "3" = 3; | ||||||
|  |         "4" = 4; | ||||||
|  |         "5" = 5; | ||||||
|  |         "6" = 6; | ||||||
|  |         "7" = 7; | ||||||
|  |         "8" = 8; | ||||||
|  |         "9" = 9; | ||||||
|  |         "a" = 10; | ||||||
|  |         "b" = 11; | ||||||
|  |         "c" = 12; | ||||||
|  |         "d" = 13; | ||||||
|  |         "e" = 14; | ||||||
|  |         "f" = 15; | ||||||
|  |         "A" = 10; | ||||||
|  |         "B" = 11; | ||||||
|  |         "C" = 12; | ||||||
|  |         "D" = 13; | ||||||
|  |         "E" = 14; | ||||||
|  |         "F" = 15; | ||||||
|  |       }; | ||||||
|  |     in { | ||||||
|  |       # Converts a hex pair directly to RGB value (0-255) | ||||||
|  |       pair = hexPair: let | ||||||
|  |         high = dictionary.${substring 0 1 hexPair}; | ||||||
|  |         low = dictionary.${substring 1 1 hexPair}; | ||||||
|  |       in | ||||||
|  |         (high * 16) + low; | ||||||
|  | 
 | ||||||
|  |       # Converts a hex set to RGB set | ||||||
|  |       set = hexSet: | ||||||
|  |         types.rgb.set { | ||||||
|  |           r = hex.toRGB.pair hexSet.r; | ||||||
|  |           g = hex.toRGB.pair hexSet.g; | ||||||
|  |           b = hex.toRGB.pair hexSet.b; | ||||||
|  |         }; | ||||||
|  |       string = hexStr: let | ||||||
|  |         rgbSet = hex.toRGB.set (hex.toSet hexStr); | ||||||
|  |       in | ||||||
|  |         types.rgb.string rgbSet.r rgbSet.g rgbSet.b; | ||||||
|  |     }; | ||||||
|  |     toHSL = { | ||||||
|  |       set = hexStr: let | ||||||
|  |         rgbSet = hex.toRGB.set (hex.toSet hexStr); | ||||||
|  |       in | ||||||
|  |         rgb.toHSL.set rgbSet; | ||||||
|  | 
 | ||||||
|  |       string = hexStr: let | ||||||
|  |         hslSet = hex.toHSL.set hexStr; | ||||||
|  |       in | ||||||
|  |         types.hsl.string hslSet.h hslSet.s hslSet.l; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  |   rgb = { | ||||||
|  |     toHex = { | ||||||
|  |       set = rgbSet: let | ||||||
|  |         # Convert decimal to two-digit hex | ||||||
|  |         toHexPair = num: let | ||||||
|  |           hex = lib.toLower (lib.toHexString num); | ||||||
|  |           # Pad with leading zero if single digit | ||||||
|  |           padded = | ||||||
|  |             if (builtins.stringLength hex) == 1 | ||||||
|  |             then "0${hex}" | ||||||
|  |             else hex; | ||||||
|  |         in | ||||||
|  |           padded; | ||||||
|  |       in | ||||||
|  |         types.hex.set { | ||||||
|  |           r = toHexPair rgbSet.r; | ||||||
|  |           g = toHexPair rgbSet.g; | ||||||
|  |           b = toHexPair rgbSet.b; | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |       string = rgbStr: let | ||||||
|  |         hexSet = rgb.toHex.set rgbStr; | ||||||
|  |       in | ||||||
|  |         types.hex.string hexSet.r hexSet.g hexSet.b; | ||||||
|  |     }; | ||||||
|  |     toHSL = { | ||||||
|  |       set = rgbSet: let | ||||||
|  |         # Normalize RGB values to 0-1 range | ||||||
|  |         r = rgbSet.r / 255.0; | ||||||
|  |         g = rgbSet.g / 255.0; | ||||||
|  |         b = rgbSet.b / 255.0; | ||||||
|  | 
 | ||||||
|  |         # Find min, max and delta | ||||||
|  |         c_max = max (max r g) b; | ||||||
|  |         c_min = min (min r g) b; | ||||||
|  |         delta = c_max - c_min; | ||||||
|  | 
 | ||||||
|  |         # Calculate HSL values | ||||||
|  |         h = | ||||||
|  |           if delta == 0.0 | ||||||
|  |           then 0.0 | ||||||
|  |           else if c_max == r | ||||||
|  |           then 60.0 * (math.mod ((g - b) / delta) 6) | ||||||
|  |           else if c_max == g | ||||||
|  |           then 60.0 * ((b - r) / delta + 2) | ||||||
|  |           else 60.0 * ((r - g) / delta + 4); | ||||||
|  | 
 | ||||||
|  |         l = (c_max + c_min) / 2; | ||||||
|  | 
 | ||||||
|  |         s = | ||||||
|  |           if delta == 0.0 | ||||||
|  |           then 0.0 | ||||||
|  |           else delta / (1 - (math.abs (2 * l - 1))); | ||||||
|  |       in | ||||||
|  |         types.hsl.set { | ||||||
|  |           inherit h; | ||||||
|  |           s = math.clamp 0.0 1.0 s; | ||||||
|  |           l = math.clamp 0.0 1.0 l; | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |       string = rgbStr: let | ||||||
|  |         hslSet = rgb.toHSL.set (hex.toRGB.set (hex.toSet rgbStr)); | ||||||
|  |       in | ||||||
|  |         types.hsl.string hslSet.h hslSet.s hslSet.l; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  |   hsl = { | ||||||
|  |     toRGB = { | ||||||
|  |       set = hslSet: let | ||||||
|  |         inherit (hslSet) h s l; | ||||||
|  | 
 | ||||||
|  |         # Calculate chroma | ||||||
|  |         c = (1 - (math.abs (2 * l - 1))) * s; | ||||||
|  |         # Calculate h prime (h') | ||||||
|  |         hp = h / 60.0; | ||||||
|  |         # Calculate x | ||||||
|  |         x = c * (1 - math.abs ((math.mod hp 2) - 1)); | ||||||
|  |         # Calculate m | ||||||
|  |         m = l - c / 2; | ||||||
|  | 
 | ||||||
|  |         # Get initial RGB values based on h' | ||||||
|  |         rgb' = | ||||||
|  |           if hp <= 1 | ||||||
|  |           then { | ||||||
|  |             r = c; | ||||||
|  |             g = x; | ||||||
|  |             b = 0; | ||||||
|  |           } | ||||||
|  |           else if hp <= 2 | ||||||
|  |           then { | ||||||
|  |             r = x; | ||||||
|  |             g = c; | ||||||
|  |             b = 0; | ||||||
|  |           } | ||||||
|  |           else if hp <= 3 | ||||||
|  |           then { | ||||||
|  |             r = 0; | ||||||
|  |             g = c; | ||||||
|  |             b = x; | ||||||
|  |           } | ||||||
|  |           else if hp <= 4 | ||||||
|  |           then { | ||||||
|  |             r = 0; | ||||||
|  |             g = x; | ||||||
|  |             b = c; | ||||||
|  |           } | ||||||
|  |           else if hp <= 5 | ||||||
|  |           then { | ||||||
|  |             r = x; | ||||||
|  |             g = 0; | ||||||
|  |             b = c; | ||||||
|  |           } | ||||||
|  |           else { | ||||||
|  |             r = c; | ||||||
|  |             g = 0; | ||||||
|  |             b = x; | ||||||
|  |           }; | ||||||
|  |         # Final RGB values | ||||||
|  |       in | ||||||
|  |         types.rgb.set { | ||||||
|  |           r = math.round ((rgb'.r + m) * 255); | ||||||
|  |           g = math.round ((rgb'.g + m) * 255); | ||||||
|  |           b = math.round ((rgb'.b + m) * 255); | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |       string = hslStr: let | ||||||
|  |         rgbSet = hsl.toRGB.set hslStr; | ||||||
|  |       in | ||||||
|  |         types.rgb.string rgbSet.r rgbSet.g rgbSet.b; | ||||||
|  |     }; | ||||||
|  |     toHex = { | ||||||
|  |       set = {}; | ||||||
|  |       string = color: color; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  | in {inherit hex hsl rgb;} | ||||||
							
								
								
									
										51
									
								
								outputs/lib/color/types.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								outputs/lib/color/types.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,51 @@ | ||||||
|  | { | ||||||
|  |   check, | ||||||
|  |   math, | ||||||
|  |   ... | ||||||
|  | }: let | ||||||
|  |   inherit (math) round; | ||||||
|  |   hex = { | ||||||
|  |     set = { | ||||||
|  |       r, | ||||||
|  |       g, | ||||||
|  |       b, | ||||||
|  |     }: let | ||||||
|  |       attrs = {inherit r g b;}; | ||||||
|  |     in | ||||||
|  |       assert check.hex.set attrs || throw "Invalid Hex values: r=${toString r}, g=${toString g}, b=${toString b}"; attrs; | ||||||
|  | 
 | ||||||
|  |     string = r: g: b: let | ||||||
|  |       str = "${r}${g}${b}"; | ||||||
|  |     in | ||||||
|  |       assert check.hex.string str || throw "Invalid Hex value: ${str}"; str; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   rgb = { | ||||||
|  |     string = r: g: b: let | ||||||
|  |       str = "${toString r},${toString g},${toString b}"; | ||||||
|  |     in | ||||||
|  |       assert check.rgb.string str || throw "Invalid RBG string format: ${str}"; str; | ||||||
|  |     set = { | ||||||
|  |       r, | ||||||
|  |       g, | ||||||
|  |       b, | ||||||
|  |     }: let | ||||||
|  |       attrs = {inherit r g b;}; | ||||||
|  |     in | ||||||
|  |       assert check.rgb.set attrs || throw "Invalid RGB values: r=${toString r}, g=${toString g}, b=${toString b}"; attrs; | ||||||
|  |   }; | ||||||
|  |   hsl = { | ||||||
|  |     string = h: s: l: let | ||||||
|  |       str = "${toString (round h)}, ${toString (round (s * 100))}%, ${toString (round (l * 100))}%"; | ||||||
|  |     in | ||||||
|  |       assert check.hsl.string str || throw "Invalid HSL values: ${str}"; str; | ||||||
|  |     set = { | ||||||
|  |       h, | ||||||
|  |       s, | ||||||
|  |       l, | ||||||
|  |     }: let | ||||||
|  |       attrs = {inherit h s l;}; | ||||||
|  |     in | ||||||
|  |       assert check.hsl.set attrs || throw "Invalid HSL values: h=${toString h}, s=${toString s}, l=${toString l}"; attrs; | ||||||
|  |   }; | ||||||
|  | in {inherit hex hsl rgb;} | ||||||
							
								
								
									
										122
									
								
								outputs/lib/color/utils.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								outputs/lib/color/utils.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,122 @@ | ||||||
|  | { | ||||||
|  |   math, | ||||||
|  |   types, | ||||||
|  |   translate, | ||||||
|  | }: let | ||||||
|  |   # base modification function | ||||||
|  |   modifyHSL = hexStr: modifications: let | ||||||
|  |     # convert hex to HSL | ||||||
|  |     hslSet = translate.hex.toHSL.set hexStr; | ||||||
|  |     # apply modifications to get new HSL values | ||||||
|  |     newHSL = types.hsl.set { | ||||||
|  |       inherit (hslSet) h; # keep hue | ||||||
|  |       l = math.clamp 0.0 1.0 (hslSet.l + (modifications.l or 0.0)); | ||||||
|  |       s = math.clamp 0.0 1.0 (hslSet.s + (modifications.s or 0.0)); | ||||||
|  |     }; | ||||||
|  |     # convert back to hex | ||||||
|  |     rgbSet = translate.hsl.toRGB.set newHSL; | ||||||
|  |   in | ||||||
|  |     translate.rgb.toHex.string rgbSet; | ||||||
|  | 
 | ||||||
|  |   lighten = amount: hexStr: | ||||||
|  |     modifyHSL hexStr {l = amount / 100.0;}; | ||||||
|  | 
 | ||||||
|  |   darken = amount: hexStr: | ||||||
|  |     modifyHSL hexStr {l = (amount * -1) / 100.0;}; | ||||||
|  | 
 | ||||||
|  |   saturate = amount: hexStr: | ||||||
|  |     modifyHSL hexStr {s = amount / 100.0;}; | ||||||
|  | 
 | ||||||
|  |   desaturate = amount: hexStr: | ||||||
|  |     modifyHSL hexStr {s = (amount * -1) / 100.0;}; | ||||||
|  | 
 | ||||||
|  |   mkDarkColorScale = base: { | ||||||
|  |     up4 = desaturate 24 (lighten 12 base); | ||||||
|  |     up3 = desaturate 18 (lighten 9 base); | ||||||
|  |     up2 = desaturate 12 (lighten 6 base); | ||||||
|  |     up1 = desaturate 6 (lighten 3 base); | ||||||
|  |     inherit base; | ||||||
|  |     down1 = desaturate 6 (darken 3 base); | ||||||
|  |     down2 = desaturate 12 (darken 6 base); | ||||||
|  |     down3 = desaturate 18 (darken 9 base); | ||||||
|  |     down4 = desaturate 24 (darken 12 base); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   mkLightColorScale = base: { | ||||||
|  |     down4 = desaturate 24 (lighten 12 base); | ||||||
|  |     down3 = desaturate 18 (lighten 9 base); | ||||||
|  |     down2 = desaturate 12 (lighten 6 base); | ||||||
|  |     down1 = desaturate 6 (lighten 3 base); | ||||||
|  |     inherit base; | ||||||
|  |     up1 = desaturate 6 (darken 3 base); | ||||||
|  |     up2 = desaturate 12 (darken 6 base); | ||||||
|  |     up3 = desaturate 18 (darken 9 base); | ||||||
|  |     up4 = desaturate 24 (darken 12 base); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   mkDarkColorScheme = { | ||||||
|  |     shades, | ||||||
|  |     primary, | ||||||
|  |     secondary, | ||||||
|  |     red, | ||||||
|  |     orange, | ||||||
|  |     yellow, | ||||||
|  |     olive, | ||||||
|  |     green, | ||||||
|  |     teal, | ||||||
|  |     blue, | ||||||
|  |     violet, | ||||||
|  |     purple, | ||||||
|  |     pink, | ||||||
|  |     brown, | ||||||
|  |   } @ args: { | ||||||
|  |     shade-50 = args.shades."50"; | ||||||
|  |     shade-100 = args.shades."100"; | ||||||
|  |     shade-150 = args.shades."150"; | ||||||
|  |     shade-200 = args.shades."200"; | ||||||
|  |     shade-250 = args.shades."250"; | ||||||
|  |     shade-300 = args.shades."300"; | ||||||
|  |     shade-350 = args.shades."350"; | ||||||
|  |     shade-400 = args.shades."400"; | ||||||
|  |     shade-450 = args.shades."450"; | ||||||
|  |     shade-500 = args.shades."500"; | ||||||
|  |     shade-550 = args.shades."550"; | ||||||
|  |     shade-600 = args.shades."600"; | ||||||
|  |     shade-650 = args.shades."650"; | ||||||
|  |     shade-700 = args.shades."700"; | ||||||
|  |     shade-750 = args.shades."750"; | ||||||
|  |     shade-800 = args.shades."800"; | ||||||
|  |     shade-850 = args.shades."850"; | ||||||
|  |     shade-900 = args.shades."900"; | ||||||
|  | 
 | ||||||
|  |     primary = mkDarkColorScale args.primary; | ||||||
|  |     secondary = { | ||||||
|  |       up-1 = args.shade."550"; | ||||||
|  |       up-2 = args.shade."500"; | ||||||
|  |       up-3 = args.shade."450"; | ||||||
|  |       up-4 = args.shade."400"; | ||||||
|  |       up-5 = args.shade."350"; | ||||||
|  |       up-6 = args.shade."300"; | ||||||
|  |       up-7 = args.shade."250"; | ||||||
|  |       up-8 = args.shade."200"; | ||||||
|  |       up-9 = args.shade."150"; | ||||||
|  |       up-10 = args.shade."100"; | ||||||
|  |       base = args.shade."700"; | ||||||
|  |       down-1 = args.shade."650"; | ||||||
|  |       down-2 = args.shade."700"; | ||||||
|  |     }; | ||||||
|  |     red = mkDarkColorScale args.red; | ||||||
|  |     orange = mkDarkColorScale args.orange; | ||||||
|  |     yellow = mkDarkColorScale args.yellow; | ||||||
|  |     olive = mkDarkColorScale args.olive; | ||||||
|  |     green = mkDarkColorScale args.green; | ||||||
|  |     teal = mkDarkColorScale args.teal; | ||||||
|  |     blue = mkDarkColorScale args.blue; | ||||||
|  |     violet = mkDarkColorScale args.violet; | ||||||
|  |     purple = mkDarkColorScale args.purple; | ||||||
|  |     pink = mkDarkColorScale args.pink; | ||||||
|  |     brown = mkDarkColorScale args.brown; | ||||||
|  |   }; | ||||||
|  | in { | ||||||
|  |   inherit lighten darken saturate desaturate mkLightColorScale mkDarkColorScale mkDarkColorScheme; | ||||||
|  | } | ||||||
|  | @ -4,10 +4,30 @@ | ||||||
|   inputs, |   inputs, | ||||||
|   ... |   ... | ||||||
| }: let | }: let | ||||||
|   # My person functions |   # my scuffed lib | ||||||
|   ook-lib = { |   ook-lib = { | ||||||
|     builders = import ./builders.nix {inherit self lib inputs;}; |     builders = import ./builders.nix {inherit self lib inputs;}; | ||||||
|     mkNeovim = import ./mkNeovim.nix {inherit inputs;}; |     mkNeovim = import ./mkNeovim.nix {inherit inputs;}; | ||||||
|  |     math = import ./math.nix {inherit lib;}; | ||||||
|  |     color = let | ||||||
|  |       check = import ./color/check.nix {inherit lib;}; | ||||||
|  |       types = import ./color/types.nix { | ||||||
|  |         inherit (ook-lib) math; | ||||||
|  |         inherit check; | ||||||
|  |       }; | ||||||
|  |       translate = import ./color/translate.nix { | ||||||
|  |         inherit lib; | ||||||
|  |         inherit (ook-lib) math; | ||||||
|  |         inherit types; | ||||||
|  |       }; | ||||||
|  |       utils = import ./color/utils.nix { | ||||||
|  |         inherit (ook-lib) math; | ||||||
|  |         inherit types translate; | ||||||
|  |       }; | ||||||
|  |     in { | ||||||
|  |       inherit check types translate; | ||||||
|  |       inherit (utils) lighten darken saturate desaturate mkColorScale; | ||||||
|  |     }; | ||||||
|   }; |   }; | ||||||
| in { | in { | ||||||
|   _module.args.ook.lib = ook-lib; |   _module.args.ook.lib = ook-lib; | ||||||
|  |  | ||||||
							
								
								
									
										46
									
								
								outputs/lib/math.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								outputs/lib/math.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,46 @@ | ||||||
|  | {lib}: let | ||||||
|  |   inherit (lib) min max; | ||||||
|  |   inherit (builtins) floor ceil; | ||||||
|  | 
 | ||||||
|  |   # basic math functions | ||||||
|  |   # credits to github:xddxdd/nix-math | ||||||
|  | 
 | ||||||
|  |   abs = x: | ||||||
|  |     if x < 0 | ||||||
|  |     then 0 - x | ||||||
|  |     else x; | ||||||
|  | 
 | ||||||
|  |   clamp = a: b: v: min (max v (min a b)) (max a b); | ||||||
|  | 
 | ||||||
|  |   round = x: | ||||||
|  |     if (x - floor x) < 0.5 | ||||||
|  |     then floor x | ||||||
|  |     else ceil x; | ||||||
|  | 
 | ||||||
|  |   hasFraction = x: let | ||||||
|  |     splitted = lib.splitString "." (builtins.toString x); | ||||||
|  |   in | ||||||
|  |     builtins.length splitted >= 2 && builtins.length (builtins.filter (ch: ch != "0") (lib.stringToCharacters (builtins.elemAt splitted 1))) > 0; | ||||||
|  | 
 | ||||||
|  |   div = a: b: let | ||||||
|  |     divideExactly = !(hasFraction (1.0 * a / b)); | ||||||
|  |     offset = | ||||||
|  |       if divideExactly | ||||||
|  |       then 0 | ||||||
|  |       else (0 - 1); | ||||||
|  |   in | ||||||
|  |     if b < 0 | ||||||
|  |     then offset - div a (0 - b) | ||||||
|  |     else if a < 0 | ||||||
|  |     then offset - div (0 - a) b | ||||||
|  |     else floor (1.0 * a / b); | ||||||
|  | 
 | ||||||
|  |   mod = a: b: | ||||||
|  |     if b < 0 | ||||||
|  |     then 0 - mod (0 - a) (0 - b) | ||||||
|  |     else if a < 0 | ||||||
|  |     then mod (b - mod (0 - a) b) b | ||||||
|  |     else a - b * (div a b); | ||||||
|  | in { | ||||||
|  |   inherit round mod abs hasFraction clamp; | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue