bahaghari/lib: init math subset

In preparation for implementing the colorspace library subset.
This commit is contained in:
Gabriel Arazas 2024-02-29 22:06:33 +08:00
parent 9fde40828b
commit 878dddea77
No known key found for this signature in database
GPG Key ID: ADE0C41DAB221FCC
6 changed files with 170 additions and 27 deletions

View File

@ -15,13 +15,15 @@ pkgs.lib.makeExtensible
{
trivial = callLibs ./trivial.nix;
hex = callLibs ./hex.nix;
math = callLibs ./math.nix;
# Dedicated module sets are not supposed to have any of its functions as
# a top-level attribute.
tinted-theming = callLibs ./tinted-theming.nix;
inherit (self.trivial) importYAML toYAML toBaseDigitsWithGlyphs
generateGlyphSet generateConversionTable generateBaseDigitType pow;
generateGlyphSet generateConversionTable generateBaseDigitType;
inherit (self.hex) isHexString;
inherit (self.math) abs pow percentage;
})

View File

@ -0,0 +1,108 @@
# A little math utility for common operations. Don't expect any high-level
# mathematical operations nor godly optimizations expected from a typical math
# library, it's just basic high school type of shit in all aspects.
{ pkgs, lib }:
rec {
/* Returns the absolute value of the given number.
Type: abs :: Int -> Int
Example:
abs -4
=> 4
abs (1 / 5)
=> 0.2
*/
abs = number:
if number < 0 then -(number) else number;
/* Exponentiates the given base with the exponent.
Type: pow :: Int -> Int -> Int
Example:
pow 2 3
=> 8
pow 6 4
=> 1296
*/
pow = base: exponent:
# I'll just make this as a tail recursive function instead.
let
absValue = abs exponent;
iter = product: counter: max-count:
if counter > max-count
then product
else iter (product * base) (counter + 1) max-count;
value = iter 1 1 absValue;
in
if exponent < 0 then (1 / value) else value;
/* Given a number, make it grow by given amount of percentage.
A value of 100 should make the number doubled.
Type: grow :: Number -> Number -> Number
Example:
grow 4 50.0
=> 2
grow 55.5 100
=> 111
*/
grow = number: value:
number + (percentage number value);
/* Given a number, make it smaller by given amount of percentage.
A value of 100 should zero the number.
Type: shrink :: Number -> Number -> Number
Example:
shrink 4 50.0
=> 2
shrink 55.5 100
=> 0
*/
shrink = number: value:
number - (percentage number value);
/* Given a number, return its value by the given percentage.
Type: percentage :: Number -> Number -> Number
Example:
percentage 4 100.0
=> 4
percentage 5 200.0
=> 10
*/
percentage = number: value:
number / (100.0 / value);
/* Given a number, round up (or down) its number to the nearest integer.
Type: round :: Number -> Number
Example:
round 3.5
=> 4
round 2.3
=> 2
round 2.7
=> 3
*/
round = number:
let
number' = builtins.floor number;
difference = number - number';
in
if difference >= 0.5 then (number' + 1) else number';
}

View File

@ -142,25 +142,4 @@ rec {
in
pkgs.lib.foldl (sum: v: sum + v) 0 convertDigitToDec;
};
/* Exponentiates the given base with the exponent.
Type: pow :: Int -> Int -> Int
Example:
pow 2 3
=> 8
pow 6 4
=> 1296
*/
pow = base: exponent:
# I'll just make this linearly recursive instead.
let
iter = product: counter: max-count:
if counter > max-count
then product
else iter (product * base) (counter + 1) max-count;
in
iter 1 1 exponent;
}

View File

@ -5,6 +5,7 @@ let
in
{
hex = import ./hex.nix { inherit pkgs lib; };
math = import ./math.nix { inherit pkgs lib; };
trivial = import ./trivial { inherit pkgs lib; };
tinted-theming = import ./tinted-theming { inherit pkgs lib; };
}

View File

@ -0,0 +1,58 @@
{ pkgs, lib }:
pkgs.lib.runTests {
testMathPowPositive = {
expr = lib.math.pow 2 8;
expected = 256;
};
testMathPowNegative = {
expr = lib.math.pow 2.0 (-1);
expected = 0.5;
};
testMathPowZero = {
expr = lib.math.pow 34 0;
expected = 1;
};
testMathAbsoluteValue = {
expr = lib.math.abs 5493;
expected = 5493;
};
testMathAbsoluteValue2 = {
expr = lib.math.abs (-435354);
expected = 435354;
};
testMathPercentage = {
expr = lib.math.percentage 100 50;
expected = 50;
};
testMathPercentage2 = {
expr = lib.math.percentage 453 13;
expected = 58.89;
};
testMathGrow = {
expr = lib.math.grow 12 500;
expected = 72;
};
testMathGrow2 = {
expr = lib.math.grow 5.5 55.5;
expected = 8.5525;
};
testMathRoundDown = {
expr = lib.math.round 2.3;
expected = 2;
};
testMathRoundUp = {
expr = lib.math.round 2.8;
expected = 3;
};
}

View File

@ -210,9 +210,4 @@ pkgs.lib.runTests {
expr = lib.trivial.toYAML { } { hello = "there"; };
expected = "{\"hello\":\"there\"}";
};
testPow = {
expr = lib.trivial.pow 2 8;
expected = 256;
};
}