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>
|
||||
|
||||
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
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
|
@ -14,8 +14,8 @@ rec {
|
||||
ln10 = 2.302585092994046;
|
||||
ln2 = 0.6931471805599453;
|
||||
|
||||
# The minimum precision for our functions that need them.
|
||||
epsilon = pow 10 (-13);
|
||||
# The precision target for our functions that need them.
|
||||
epsilon = pow 0.1 13;
|
||||
};
|
||||
|
||||
/* Returns the absolute value of the given number.
|
||||
@ -32,6 +32,20 @@ rec {
|
||||
abs = 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.
|
||||
|
||||
Type: pow :: Int -> Int -> Int
|
||||
@ -314,6 +328,60 @@ rec {
|
||||
*/
|
||||
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.
|
||||
|
||||
Type: radiansToDegrees :: Number -> Number
|
||||
|
@ -208,7 +208,7 @@ lib.runTests {
|
||||
};
|
||||
|
||||
testMathSqrt = {
|
||||
expr = self.math.sqrt 4;
|
||||
expr = round' (self.math.sqrt 4);
|
||||
expected = 2;
|
||||
};
|
||||
|
||||
@ -362,4 +362,93 @@ lib.runTests {
|
||||
expr = self.math.round' (-3) (self.math.radiansToDegrees 4.5);
|
||||
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