bahaghari/lib: init generateBaseDigitType

This commit is contained in:
Gabriel Arazas 2024-02-28 18:39:00 +08:00
parent ac75f74d36
commit 29d4bb657a
No known key found for this signature in database
GPG Key ID: ADE0C41DAB221FCC
3 changed files with 125 additions and 35 deletions

View File

@ -21,6 +21,6 @@ pkgs.lib.makeExtensible
tinted-theming = callLibs ./tinted-theming.nix;
inherit (self.trivial) importYAML toYAML toBaseDigitsWithGlyphs
generateGlyphSet generateConversionTable pow;
inherit (self.hex) toHexString isHexString hexToDec;
generateGlyphSet generateConversionTable generateBaseDigitType pow;
})

View File

@ -1,6 +1,6 @@
{ pkgs, lib }:
{
rec {
inherit (pkgs.lib.generators) toYAML;
/* Read YAML files into a Nix expression similar to lib.importJSON and
@ -99,6 +99,59 @@
in
pkgs.lib.listToAttrs glyphsList';
/* A factory function for generating an attribute set containing a glyph
set, a conversion table, and a conversion function to and from decimal.
Accepts the same list as `generateGlyphSet` and
`generateConversionTable` where it assumes it is sorted and
zero-indexed.
Type: generateBaseDigitType :: [ String ] -> Attrs
Example:
generateBaseDigitType [ "0" "1" ]
=> {
base = 2;
glyphSet = { "0" = "0"; "1" = "1"; };
conversionTable = { "0" = 0; "1" = 1; };
isValidDigit = <function>;
fromDec = <function>;
toDec = <function>;
}
*/
generateBaseDigitType = glyphsList: rec {
base = pkgs.lib.length glyphsList;
glyphSet = generateGlyphSet glyphsList;
conversionTable = generateConversionTable glyphsList;
# Unfortunately, these functions cannot handle negative numbers unless we
# implement something like Two's complement. For now, we're not worrying
# about that since most of the use cases here will be mostly for color
# generation that typically uses hexadecimal (RGB). Plus I don't want to
# open a can of worms about implementing this with stringy types.
fromDec = decimal:
let
iter = product: value:
let
quotient = value / base;
remainder = value - (base * quotient);
baseDigit = glyphSet.${builtins.toString remainder} + product;
in
if quotient <= 0
then baseDigit
else iter baseDigit quotient;
in
iter "" decimal;
toDec = digit:
let
chars = pkgs.lib.stringToCharacters digit;
maxDigits = (pkgs.lib.length chars) - 1;
convertDigitToDec =
pkgs.lib.lists.imap0 (i: v: conversionTable.${v} * (pow base (maxDigits - i))) chars;
in
pkgs.lib.foldl (sum: v: sum + v) 0 convertDigitToDec;
};
/* Exponentiates the given base with the exponent.
Type: pow :: Int -> Int -> Int

View File

@ -12,6 +12,33 @@ let
"7" = "H";
};
base24GlyphsList = [
"0"
"1"
"2"
"3"
"4"
"5"
"6"
"7"
"8"
"9"
"A"
"B"
"C"
"D"
"E"
"F"
"G"
"H"
"I"
"J"
"K"
"L"
"M"
"N"
];
customBase24Glyphs = {
"0" = "0";
"1" = "1";
@ -33,11 +60,13 @@ let
"17" = "H";
"18" = "I";
"19" = "J";
"20" = "M";
"21" = "N";
"22" = "O";
"23" = "P";
"20" = "K";
"21" = "L";
"22" = "M";
"23" = "N";
};
base24Set = lib.trivial.generateBaseDigitType base24GlyphsList;
in
pkgs.lib.runTests {
testGenerateCustomGlyphSet = {
@ -46,34 +75,7 @@ pkgs.lib.runTests {
};
testGenerateBase24GlyphSet = {
expr =
lib.trivial.generateGlyphSet
[
"0"
"1"
"2"
"3"
"4"
"5"
"6"
"7"
"8"
"9"
"A"
"B"
"C"
"D"
"E"
"F"
"G"
"H"
"I"
"J"
"M"
"N"
"O"
"P"
];
expr = lib.trivial.generateGlyphSet base24GlyphsList;
expected = customBase24Glyphs;
};
@ -91,6 +93,41 @@ pkgs.lib.runTests {
};
};
testGenerateConversionTable2 = {
expr = lib.trivial.generateConversionTable
[ "0" "1" "2" "3" "4" "5" "6" "7"
"8" "9" "A" "B" "C" "D" "E" "F" ];
expected = {
"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;
};
};
# Testing out the custom factory methods if they are working as intended.
testCustomBaseDigitSetToDec = {
expr = base24Set.toDec "12H";
expected = 641;
};
testCustomBaseDigitSetFromDec = {
expr = base24Set.fromDec 641;
expected = "12H";
};
testBaseDigitWithCustomOctalGlyph = {
expr = lib.trivial.toBaseDigitsWithGlyphs 8 9 customOctalGlyphs;
expected = "BB";