mirror of
https://github.com/foo-dogsquared/nixos-config.git
synced 2025-01-30 22:57:55 +00:00
bahaghari/lib: add trigonometric functions to math subset
Code taken from https://lantian.pub/en/article/modify-computer/nix-trigonometric-math-library-from-zero.lantian/ with proper attributions (hopefully).
This commit is contained in:
parent
4d32203d4d
commit
e3122bfd24
@ -1,5 +1,9 @@
|
|||||||
Copyright (c) 2024 Gabriel Arazas <foodogsquared@foodogsquared.one>
|
Copyright (c) 2024 Gabriel Arazas <foodogsquared@foodogsquared.one>
|
||||||
|
|
||||||
|
Program uses the following files/implementations from other authors;
|
||||||
|
see their respective license headers for more details:
|
||||||
|
lib/math.nix, specifically the sin, cos, tan, and arctan functions: Copyright (c) 2023 Yuhui Xu
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
|
@ -14,8 +14,8 @@ rec {
|
|||||||
ln10 = 2.302585092994046;
|
ln10 = 2.302585092994046;
|
||||||
ln2 = 0.6931471805599453;
|
ln2 = 0.6931471805599453;
|
||||||
|
|
||||||
# The minimum precision for our functions that need them.
|
# The precision target for our functions that need them.
|
||||||
epsilon = pow 10 (-13);
|
epsilon = pow 0.1 13;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Returns the absolute value of the given number.
|
/* Returns the absolute value of the given number.
|
||||||
@ -32,6 +32,20 @@ rec {
|
|||||||
abs = number:
|
abs = number:
|
||||||
if number < 0 then -(number) else number;
|
if number < 0 then -(number) else number;
|
||||||
|
|
||||||
|
/* Given a Nix number, force it to be a floating value.
|
||||||
|
|
||||||
|
Type: toFloat :: Number -> Float
|
||||||
|
|
||||||
|
Example:
|
||||||
|
toFloat 5
|
||||||
|
=> 5.0
|
||||||
|
|
||||||
|
toFloat 59.0
|
||||||
|
=> 59.0
|
||||||
|
*/
|
||||||
|
toFloat = x:
|
||||||
|
1.0 * x;
|
||||||
|
|
||||||
/* Exponentiates the given base with the exponent.
|
/* Exponentiates the given base with the exponent.
|
||||||
|
|
||||||
Type: pow :: Int -> Int -> Int
|
Type: pow :: Int -> Int -> Int
|
||||||
@ -314,6 +328,60 @@ rec {
|
|||||||
*/
|
*/
|
||||||
product = builtins.foldl' builtins.mul 1;
|
product = builtins.foldl' builtins.mul 1;
|
||||||
|
|
||||||
|
# The following trigonometric functions is pretty much sourced from the following link.
|
||||||
|
# https://lantian.pub/en/article/modify-computer/nix-trigonometric-math-library-from-zero.lantian/
|
||||||
|
|
||||||
|
/* Given a number in radians, return the value applied with a sine function.
|
||||||
|
|
||||||
|
Type: sin :: Number -> Number
|
||||||
|
|
||||||
|
Example:
|
||||||
|
sin 10
|
||||||
|
=> -0.5440211108893698
|
||||||
|
|
||||||
|
sin (constants.pi / 2)
|
||||||
|
=> 1
|
||||||
|
*/
|
||||||
|
sin = x: let
|
||||||
|
x' = mod (toFloat x) (2 * constants.pi);
|
||||||
|
step = i: (pow (-1) (i - 1)) * product (lib.genList (j: x' / (j + 1)) (i * 2 - 1));
|
||||||
|
iter = value: counter: let
|
||||||
|
value' = step counter;
|
||||||
|
in
|
||||||
|
if (abs value') < constants.epsilon
|
||||||
|
then value
|
||||||
|
else iter (value' + value) (counter + 1);
|
||||||
|
in
|
||||||
|
if x < 0
|
||||||
|
then -(sin (-x))
|
||||||
|
else iter 0 1;
|
||||||
|
|
||||||
|
/* Given a number in radians, apply the cosine function.
|
||||||
|
|
||||||
|
Type: cos :: Number -> Number
|
||||||
|
|
||||||
|
Example:
|
||||||
|
cos 10
|
||||||
|
=> -0.8390715290764524
|
||||||
|
|
||||||
|
cos 0
|
||||||
|
=> 1
|
||||||
|
*/
|
||||||
|
cos = x: sin (0.5 * constants.pi - x);
|
||||||
|
|
||||||
|
/* Given a number in radians, apply the tan trigonometric function.
|
||||||
|
|
||||||
|
Type: tan :: Number -> Number
|
||||||
|
|
||||||
|
Example:
|
||||||
|
tan 0
|
||||||
|
=> 0
|
||||||
|
|
||||||
|
tan 10
|
||||||
|
=> 0.6483608274590866
|
||||||
|
*/
|
||||||
|
tan = x: (sin x) / (cos x);
|
||||||
|
|
||||||
/* Given a number in radians, convert it to degrees.
|
/* Given a number in radians, convert it to degrees.
|
||||||
|
|
||||||
Type: radiansToDegrees :: Number -> Number
|
Type: radiansToDegrees :: Number -> Number
|
||||||
|
@ -208,7 +208,7 @@ lib.runTests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
testMathSqrt = {
|
testMathSqrt = {
|
||||||
expr = self.math.sqrt 4;
|
expr = round' (self.math.sqrt 4);
|
||||||
expected = 2;
|
expected = 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -362,4 +362,93 @@ lib.runTests {
|
|||||||
expr = self.math.round' (-3) (self.math.radiansToDegrees 4.5);
|
expr = self.math.round' (-3) (self.math.radiansToDegrees 4.5);
|
||||||
expected = 257.831;
|
expected = 257.831;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# At this point, most of the things are just adjusting to the quirks of those
|
||||||
|
# accursed floating-values.
|
||||||
|
testMathSine = {
|
||||||
|
expr = round' (self.math.sin 10);
|
||||||
|
expected = round' (-0.5440211108893698);
|
||||||
|
};
|
||||||
|
|
||||||
|
testMathSine2 = {
|
||||||
|
expr = self.math.sin 0;
|
||||||
|
expected = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
testMathSine3 = let
|
||||||
|
round' = self.math.round' (-5);
|
||||||
|
in {
|
||||||
|
expr = round' (self.math.sin (self.math.constants.pi / 2));
|
||||||
|
expected = round' 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
testMathSine4 = {
|
||||||
|
expr = round' (self.math.sin 360);
|
||||||
|
expected = round' 0.9589157234143065;
|
||||||
|
};
|
||||||
|
|
||||||
|
testMathSine5 = {
|
||||||
|
expr = round' (self.math.sin 152);
|
||||||
|
expected = round' 0.933320523748862;
|
||||||
|
};
|
||||||
|
|
||||||
|
testMathSine6 = {
|
||||||
|
expr = round' (self.math.sin (-152));
|
||||||
|
expected = round' (-0.933320523748862);
|
||||||
|
};
|
||||||
|
|
||||||
|
testMathCosine = {
|
||||||
|
expr = round' (self.math.cos 10);
|
||||||
|
expected = round' (-0.8390715290764524);
|
||||||
|
};
|
||||||
|
|
||||||
|
testMathCosine2 = {
|
||||||
|
expr = round' (self.math.cos 0);
|
||||||
|
expected = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
testMathCosine3 = {
|
||||||
|
expr = round' (self.math.cos self.math.constants.pi);
|
||||||
|
expected = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
testMathCosine4 = {
|
||||||
|
expr = round' (self.math.cos (self.math.constants.pi * 2));
|
||||||
|
expected = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
testMathCosine5 = {
|
||||||
|
expr = round' (self.math.cos 1);
|
||||||
|
expected = round' 0.5403023058681398;
|
||||||
|
};
|
||||||
|
|
||||||
|
testMathCosine6 = {
|
||||||
|
expr = round' (self.math.cos 152);
|
||||||
|
expected = round' 0.35904428689111606;
|
||||||
|
};
|
||||||
|
|
||||||
|
testMathTangent = {
|
||||||
|
expr = round' (self.math.tan 10);
|
||||||
|
expected = round' 0.6483608274590866;
|
||||||
|
};
|
||||||
|
|
||||||
|
testMathTangent2 = {
|
||||||
|
expr = round' (self.math.tan 0);
|
||||||
|
expected = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
testMathTangent3 = {
|
||||||
|
expr = round' (self.math.tan (self.math.constants.pi / 4));
|
||||||
|
expected = round' (0.99999999999999999);
|
||||||
|
};
|
||||||
|
|
||||||
|
testMathTangent4 = {
|
||||||
|
expr = round' (self.math.tan 152);
|
||||||
|
expected = round' 2.5994579438382797;
|
||||||
|
};
|
||||||
|
|
||||||
|
testMathTangent5 = {
|
||||||
|
expr = round' (self.math.tan (-152));
|
||||||
|
expected = round' (-2.5994579438382797);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user