Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: math: add more special functions #24241

Closed
jxdp opened this issue Mar 4, 2018 · 10 comments
Closed

Proposal: math: add more special functions #24241

jxdp opened this issue Mar 4, 2018 · 10 comments
Labels
FrozenDueToAge Proposal WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Milestone

Comments

@jxdp
Copy link

jxdp commented Mar 4, 2018

I would like to add more special functions to the math library. I have recently started using Go as my primary language due to its simplicity to both read and write. Coming from a science background in which Python and NumPy/SciPy are heavily leveraged, however, I have noticed a distinct lack of special functions available.

It seems sensible to me to start adding these to encourage more scientists, and generally people with demand for a wider variety of mathematical functions, to start making the switch to Go.

In particular, the functions I would add are those typically found, in, say, a special functions Fortran or C++ library such as this one (http://people.sc.fsu.edu/~jburkardt/cpp_src/fn/fn.cpp).

I have actually started implementing some of these functions already. Unless there any objections, I am happy to contribute my code to the library and continue to add more.

@gopherbot gopherbot added this to the Proposal milestone Mar 4, 2018
@mvdan mvdan changed the title Proposal: Add more special functions to standard math library Proposal: math: add more special functions Mar 4, 2018
@mvdan
Copy link
Member

mvdan commented Mar 4, 2018

@jdparkinson93 could you list exactly what functions you would add, including their signatures? A proposal needs to be specific, and suggesting adding one new function is very different from adding a dozen.

@ALTree
Copy link
Member

ALTree commented Mar 4, 2018

You should also explain why these new functions need to be in the standard library and cannot be published, for example, as an external library (outside stdlib).

@bradfitz
Copy link
Contributor

bradfitz commented Mar 4, 2018

See also: https://golang.org/doc/faq#x_in_std

@bradfitz bradfitz added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Mar 4, 2018
@jxdp
Copy link
Author

jxdp commented Mar 4, 2018

Thanks all for your comments. @mvdan @ALTree @bradfitz

I hope the below addresses your points adequately. I have never made an open-source contribution before and apologise for the lack of detail in my initial post.

Truncate
Truncate(x float64) float64 => returns float64(int(x)), or NaN if x is NaN or ±Inf.

i.e. Truncate returns only the integer part and does not round. This is very similar to the Floor function except for the handling of infinities and negative numbers. For example: Floor(-15.2) = -16, but Truncate(-15.2) = -15; Floor(±Inf) = ±Inf, Truncate(±Inf) = NaN.

I think it should be included in the standard library because it is very useful and very small (easy to maintain).

The following functions (Pochhammer symbols, hypergeometric functions, incomplete/regularised gamma functions) came to my attention when I was planning to to build a model, using Go, utilising a Maxwell-Boltzmann distribution: I needed a random number generator to draw samples from.

I had planned to generate samples either from an existing generator (couldn't find one) or by inverting the Maxwell-Boltzmann CDF and using a uniformly distributed variable between 0 and 1 as is standard. However, I quickly found that the machinery did not yet exist in Go to perform such calculations. I could have switched back to Python, but instead I saw this as a good reason to start putting more machinery in place to allow for future additions to the rand library as well as the math library.

The aforementioned functions are primarily built from the standard library Gamma/Lgamma functions, with lots of simplifications for the (very many) special cases. Because they are mostly built from the Gamma functions, it does not seem to me to much of an additional burden for maintenance. Indeed, adequately commented and with appropriate variable names, the new functions could be easier to maintain than some of the existing code in the math library I have looked over in the past few days, some of which appears to be a translation of older code and does not offer much in the form of comments and often uses cryptic variable names.

The Pochhammer symbol http://mathworld.wolfram.com/PochhammerSymbol.html
Pochhammer(x, a float64) float64 => returns Poch(x, a)
Lpochhammer(x, a float64) (float64, float64) => returns ln|Poch(x, a)|, sign(Poch(x,a))

Confluent Hypergeometric functions (Gauss's, of the first kind,
and limit functions)
http://mathworld.wolfram.com/HypergeometricFunction.html

Hyp2f1(a, b, c, x float64) float64 => returns Gauss's hypergeometric function
Hyp1f1(a, b, x float64) float64 => returns confluent hypergeometric function of the first kind (special case of Hyp2f1)
Hyp0f1(b, x float64) float64 => returns the confluent hypergeometric limit function (special case of Hyp1f1)

Incomplete Gamma functions http://mathworld.wolfram.com/IncompleteGammaFunction.html
Gammalow(a, x float64) float64 => returns the lower incomplete gamma function
Gammaup(a, x float64) float64 => returns the upper incomplete gamma function
Not sure about the names for these ones; I welcome better suggestions!

Regularised Gamma functions http://mathworld.wolfram.com/RegularizedGammaFunction.html
Pgamma(a, x float64) float64 => returns the regularised lower incomplete gamma function
Qgamma(a, x float64) float64 => returns the regularised upper incomplete gamma function
Not sure about the names for these ones; I welcome better suggestions!

The following functions are not related to my previous comments about the future development of the math and rand libraries, but are commonly used. The beta and exponential integral function in particular are very "cheap" to calculate given the above functions.

The (incomplete) Beta function https://en.wikipedia.org/wiki/Beta_function http://mathworld.wolfram.com/IncompleteBetaFunction.html
Beta(x, y float64) float64 => returns the beta function B(x, y)
Beta(z, x, y float64) float64 => returns the incomplete beta function B_z(x, y)

The Airy functions and related https://en.wikipedia.org/wiki/Airy_function
Airy(x float64) float64 => returns the Airy function of the first kind Ai(x)
Bairy(x float64) => returns the Airy function of the second kind Bi(x)
Lairy(x float64) (float64, int) => returns ln|Ai(x)|, sign of Ai(x)
Lbairy(x float64) (float64, int) => returns ln|Bi(x)|, sign of Bi(x)

Exponential sum function http://mathworld.wolfram.com/ExponentialSumFunction.html
Expsum(x float64, n int) float64 => returns the sum of the first n terms of Exp(x)

Exponential integral function http://mathworld.wolfram.com/ExponentialIntegral.html
Ei(x float64) float64 => returns the exponential integral function Ei(x)

I completely understand if you believe these functions belong in an external library rather than the standard library. My belief that they should be in the standard library essentially boils down to the fact that most of the above functions are closely related to the standard library Gamma functions and seemed like a natural extension/pairing. It also seems insufficient for a fully-fledged library, though over time more contributions could make it into a worthy cause, much like NumPy/SciPy in Python.

I have a working implementation for Pochhammer(x, a) if you would be interested to see the level of maintenance that may be required (it is ~300 lines, but many of these are explanations of the results and special cases).

@mvdan
Copy link
Member

mvdan commented Mar 4, 2018

It is unlikely that a proposal to add 16 new funcs to the math package is going to be accepted. I suggest that you instead propose adding one or two funcs as a start - for example, the most generally useful and popular.

Truncate

Don't we already have Trunc?

I think it should be included in the standard library because it is very useful and very small (easy to maintain).

Note that one big factor is bloating the API. More exported funcs add complexity to the package's godoc for its users too. And of course, we're stuck with them for the foreseeable future.

@jxdp
Copy link
Author

jxdp commented Mar 4, 2018

@mvdan Trunc is again very similar but deals with infinities differently. Granted, however, it is a very avoidable difference. My gripe with Trunc returning infinities is that there is no integer representation of them in Go and hence it's possible for infinities to slip through unless one always adds additional checks. Given the use for such a function is (in my experience) usually along the lines of
if truncate(x) == x { //do something requiring x to be a non-infinite integer}
it would be more useful to have infinities return NaN instead of infinities. Maybe I should suggest it as a change - but that seems far less likely to pass.

Putting Trunc to one side, what would you recommend I do regarding the other functions?

@ALTree
Copy link
Member

ALTree commented Mar 4, 2018

most of the above functions are closely related to the standard library Gamma functions

Yes... you could fill books with a list of all the mathematical objects related the Gamma function : ) Not sure it's enough to warrant a place in a language standard library. Most of those function aren't even included in the Julia stdlib; they are in separate libraries (like https://github.com/JuliaMath/SpecialFunctions.jl and others). And Julia (unlike Go) is a language which is specifically focused on scientific/numerical computing!

It also seems insufficient for a fully-fledged library

I disagree. I'm not suggesting going the javascript/npm way with 10-lines "libraries", but here you have several rather complex mathematical functions. Code + tests + benchmarks for all of those would amount to hundreds (or more likely even thousands) of lines of code. It seems there's more than enough material for a library. Or maybe a patch to an already existing Go third party scientific library that would like to add those functions.

@jxdp
Copy link
Author

jxdp commented Mar 4, 2018

@ALTree Very fair comment and I think that ultimately you're right. I admittedly had not taken into account the additional API bloat that adding more functions to the standard library would entail.

Another consideration I've just had, that supports your idea for a separate library, is that the standard library should probably be on the "lighter" side purely so as to be able to run on as lightweight a machine as possible. Bloating the standard library with (franly) esoteric mathmatical functions beyond key functions (i.e. trig, hyperbolic trig, logarithms, gamma, erf, etc.) isn't practical.

So, to wrap this up: I'll start putting together an external library (or adding to one that could use a patch like this).

Thanks all for your help on this matter.

@dgryski
Copy link
Contributor

dgryski commented Mar 4, 2018

They might be more appropriate for https://github.com/aclements/go-moremath

@andybons
Copy link
Member

andybons commented Mar 4, 2018

So, to wrap this up: I'll start putting together an external library (or adding to one that could use a patch like this).

Closing this for now given that it appears @jdparkinson93 is going to pursue an external library instead of integrating into the stdlib. Please re-open if I misinterpreted.

@andybons andybons closed this as completed Mar 4, 2018
@golang golang locked and limited conversation to collaborators Mar 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge Proposal WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
None yet
Development

No branches or pull requests

7 participants