[Question]
  [
## Challenge
Unlike the circumference of a circle (which is as simple as \$2\pi r\$), the [circumference (arc length) of an ellipse is hard](https://en.wikipedia.org/wiki/Ellipse#Circumference).
Given the semi-major axis \$a\$ and semi-minor axis \$b\$ of an ellipse (see the image below, from Wikipedia), calculate its circumference.
By definition, you can assume \$0 < b \le a\$ for input values. The output value must be within \$10^{-6}\$ relative error from the expected answer for the given test cases.
[![enter image description here](https://i.stack.imgur.com/tZRuK.png)](https://i.stack.imgur.com/tZRuK.png)
Standard [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'") rules apply. The shortest code in bytes wins.
## Formulas
Relevant information can be found on [Wikipedia](https://en.wikipedia.org/wiki/Ellipse#Circumference) and [MathWorld](https://mathworld.wolfram.com/Ellipse.html). \$C\$ is the value of the circumference; \$e\$ and \$h\$ are helper values. The last two are Ramanujan's approximations, the first of which (the crossed-out one) does not meet the error requirements. The second approximation formula (Equation 5) barely does ([verification](https://tio.run/##ZVBNT8JAEL3vrxhuu5R@bEujHjyZGDlJwDPJNlKLgYJUDsZw0hCElOjB1LMx0ZsHY0g42n@yf6TOthIg7mEyb@a9N7MjBl39/EZ0@xeZXDzXTuXk0SKYHTcw1OsIub2/B041k7PXzEcs44Wc3f18OnLyhJxm4wjj2UmtmQnsusRTGhK1h512hOmtTOZUxitNxt8sTTQjTWT8QUty@mK4aUJVT897yzULW2Um4y9uWdaYkKHoiXB0KUK@tnOUR8HVDbes/BTOy2oIxgKsxhu1rdQBhmKBf2NBzu9hd1muXIJ0yS2tGFPVVQF3ElB8EDxMNwvuQhuhnL6btnx4MwGvhMMFUGoZB/mDNPmzYVDZqCrADUs9vk3wCCGs7/tkAIcw6FCheQyiUQ/djE7os9zXLYWMCt1jrdDMGa2QtWyy1jiFSofoanhNqaMQlhyPMUZIgCSaqwutUm4Noxw0cAKT4jVyPR4jQOEv)) for up to \$a=5b\$ (which is also the upper limit of the test cases, so you can use it for your answer).
$$
\require{enclose} \\
\begin{align}
e &= \sqrt{1-\frac{b^2}{a^2}} \\
C &= 4aE(e) = 4a\int^{\pi/2}\_{0}{\sqrt{1-e^2 \sin^2 \theta} \;d\theta} \tag{1} \\
C &= 2 \pi a \left(1-\sum^{\infty}\_{n=1}{\left(\frac{(2n-1)!!}{(2n)!!}\right)^2 \frac{e^{2n}}{2n-1}}\right) \tag{2} \\
h &= \frac{(a-b)^2}{(a+b)^2} \\
C &= \pi (a + b) \left( 1 + \sum^{\infty}\_{n=1} { \left( \frac{(2n-1)!!}{2^n n!} \right)^2 \frac{h^n}{(2n-1)^2} } \right) \tag{3} \\
C &= \pi (a + b) \sum^{\infty}\_{n=0} { \binom{1/2}{n}^2 h^n } \tag{4} \\
\enclose{horizontalstrike}{C} &\enclose{horizontalstrike}{\approx \pi \left( 3(a+b) - \sqrt{(3a+b)(a+3b)} \right)} \\
C &\approx \pi (a+b) \left( 1+ \frac{3h}{10 + \sqrt{4-3h}} \right) \tag{5}
\end{align}
$$
## Test cases
All the values for C (circumference) are calculated using Equation 4 with 1000 terms, and presented with 10 significant figures.
```
a     b     C
1     1     6.283185307
1.2   1     6.925791195
1.5   1     7.932719795
2     1     9.688448220
3     1     13.36489322
5     1     21.01004454
20    10    96.88448220
123   45    556.6359936
```
  
[Answer]
# [Wolfram Language (Mathematica)](https://www.wolfram.com/wolframscript/), 20 bytes
```
Perimeter[#~Disk~#]&
```
[Try it online!](https://tio.run/##y00syUjNTSzJTE78n277PyC1KDM3tSS1KFq5ziWzOLtOOVbtf0BRZl6Jgr5Dur5DdbWhno6hXq0OkDaCMUwhDCOojDGUNoXSRgZAhgFYqRFQzsRUr7b2/38A "Wolfram Language (Mathematica) – Try It Online")
-2 bytes from @Roman (see comments)
[Answer]
# [Python 3](https://docs.python.org/3/), ~~68~~ 67 bytes
```
f=lambda a,b,k=2:k>>9or(1-b*b/a/a)*(k-4+3/k)/k*f(a,b,k+2)+6.28319*a
```
[Try it online!](https://tio.run/##XcxBDoIwEIXhvadwOdMOlJkCERO4yzSm0VSBEDaeviYujGX55f1563u/L7PPOY5PfYWbnpUCpVGuaZqGZQOugglOnaKBVLXWu4QumQjfzgravpaL58FoXrfHvEMEJkY8/VTLwV3hcvWFDmVD3Pw/iae2Q8wf "Python 3 – Try It Online")
An exact infinite series, given sufficiently accurate values of \$2\pi \approx 6.28319\$ and \$\infty \approx 9\$.
### ~~69~~ 68 bytes
```
f=lambda a,b,k=0:k//7*.785398*a*(8-k)or f(a+b,2*(a*b)**.5,k*b/a/2+4)
```
[Try it online!](https://tio.run/##XczLCsIwEIXhvU/R5cx0mmtDo9CHmSBBibaldOPTx52YLj/@w9k@x2NdfK15fsk73aUTTlxmcytaT6SmGPw1khDEoeC6dxmkT@wIhBISqcCFkhbt@hHrtj@XAzJYtoiXn5Q7OTRuq290Whq25v/JeR4DYv0C "Python 3 – Try It Online")
Another exact series, given sufficiently accurate values of \$\frac\pi4 \approx .785398\$ and \$8 \approx 7\$. This one converges extremely quickly, using just five recursive calls for each test case! The recursion exactly preserves the invariant value
$$\left(1 + \frac{kb}{8a}\right)C(a, b) - \frac{kb}{8a}C(a + b, 2\sqrt{a b}),$$
which can then be approximated as \$(1 - \frac k8)2\pi a\$ when \$a, b\$ become sufficiently close.
[Answer]
# [R](https://www.r-project.org/), ~~60~~ 57 bytes
```
function(a,b,c=a+b,h=3*(a-b)^2/c)pi*(c+h/(10+(4-h/c)^.5))
```
[Try it online!](https://tio.run/##hc7NjoIwEMDxu09h4qWVWjsznX4ceBUNNCWQIBp2fX7WJV4kAXuaNPnN/McpdWN63po85iHl67255r7vHj@5nJrnkH67@yAqVatUVkWt2pKOojrV8oLnJB/dUaSiPQswhbCn9vV10Szl6k4Bav//QO4P8@A0BoLAZPxuHWlUnygi@wgQeQvxB/I6EnqIfgvhIi9qF4K1AdGsI1ogIE3Ohtc5XEe8QAjagDHWst3IM7MC81bR6e95gHOg5TdidtoRx0huN01/ "R – Try It Online")
Straightforward implementation of Ramanujan's 2nd approximation (eq 5).
Rather sadly, this approximation comes out as ~~much~~ more concise than a more-interesting **different approach** prompted by the comments: 'draw' a big ellipse, and measure around the edge of it (unfortunately counting the actual pixels wasn't going to work...):
**[R](https://www.r-project.org/), ~~90~~ ~~65~~ 62 bytes**
*Edit: -3 bytes by calculating hypotenuse length using `abs` value of complex number*
```
function(a,b,n=1e5)sum(4*abs(diff(b*(1-(0:n/n)^2)^.5)+1i*a/n))
```
[Try it online!](https://tio.run/##hc/dboMgFAfw@z7FSXqjnWWAoLKkr9JG2aGSKG4IS/b0jpomy5rUccPn75w/ftHW6zga9Og0XiZzwWGwHzOeFhOdDnZyWVt0hTsxlPkcx0wc2m7O3q0xWXfI2DGjb@7V5Ween4nMX5g9tGmbL3twU0DQfeuuCA7CBL299ujhqx0izmAmDx2GkE5araNv9Td0McAwJeDBR3cMdsTdHlJrsDPM0RirLbpwKzYiprnHX@zxM1qP4@3BZNa71H0YMNXb7Z59NGMF3AbLYb8uKsKbkjWypPUGIrz4ixSXtWJMyS0k/6CaqJLXTNVbiD/EU6RqGiEazulzVD4gVpKyEk1qx58j@YA4I5RRKoQUG/Hoqhi9K1WR/@MxvgYU8o6krEhVSqXKarcsPw "R – Try It Online")
**How?** (ungolfed code):
```
circumference_of_ellipse=
function(a,b                # a,b = axes of ellipse
n=1e6){                     # n = number of pixels to 'draw' across 'a' axis
x=a*0:n/n                   # x coordinates = n pixels from 0 to a
y=b*(1-(x/a)^2)^.5)         # y coordinates = to satisfy (x/a)^2 + (y/b)^2 =1
                            # we could actually draw the (quarter) ellipse here
                            # with 'plot(x,y)'
step_y=diff(y)              # step_y = change in y for each step of x
step_x=a/n                  # step_x = size of each step of x
h=(step_y^2+step_x^2)^.5    # h=hypotenuse of triangle formed by step_y & step_x
sum(4*h)                    # sum all the hypotenuses and multiply by 4
                            # (since we only 'drew' a quarter of the ellipse)
```
[Answer]
# [APL (Dyalog Unicode)](https://www.dyalog.com/), ~~28~~ ~~25~~ 23 [bytes](https://github.com/abrudz/SBCS)
Thanks to [Bubbler](https://codegolf.stackexchange.com/users/78410/bubbler) for -5 bytes!
Assumes `⎕IO←0`.
```
f←○1⊥+×9(×⍨*×.5!⍨⊢)∘⍳⍨-÷+
```
[Try it online!](https://tio.run/##SyzI0U2pTMzJT///qG@qp/@jtgkGXI9656YBGY@mdxs@6lqqfXi6kdaj3hUaeqaKQOpR72ZLzcPTLbUedcwAsoEiuoe3a@PSA1atAWIeng7V37VYE6TjP6pyS43D04GyWghlizRRbAC5TwGoRcFQIU3BkAvO0zNC45ui8FFljVF4aCoNQFwDhElGINUmpv8B "APL (Dyalog Unicode) – Try It Online")
This calculates
$$
\pi \cdot \sum\_{n=0}^{8} (a+b) \cdot \left( h^{\prime n} \binom{1/2}{n} \right) ^2 \qquad h^\prime = {{a-b}\over{a+b}}
$$
which is a good enough approximation using the 4th formula.
For the explanation the function will be split into two. `f` is the main function and `g` calculates \$ \left( \alpha^{\prime n} \binom{1/2}{n} \right) ^2 \$ for \$n\$ from \$0\$ to \$\omega-1\$:
```
g ← (×⍨*×.5!⍨⊢)∘⍳
f ← ○1⊥+×9g⍨-÷+
```
Starting with `a f b` from the right:
`-÷+` calculates \$h^\prime = (a-b)÷(a+b)\$.  
`g⍨` is `g` commuted => `9 g⍨ h' ≡ h' g 9`. `g` returns a vector of the 9 values of \$\left( h^{\prime n} \binom{1/2}{n} \right) ^2\$.  
`+×` multiplies \$a + b\$ to this vector.  
`1⊥` converts the resulting vector from base 1, which is the same as summing the vector.  
`○` multiplies the resulting number by \$\pi\$.
Now to `h' g 9`:
`⍳` is an index generator, with `⎕IO←0`, `⍳9` results in the vector `0 1 ... 8`.  
The remaining train `×⍨*×.5!⍨⊢` is now called with \$h^\prime\$ as a left argument and the vector \$v = (0,1, \cdots, 8)\$ as a right argument:
`.5!⍨⊢` is the commuted binomial coefficient called with the vector `v` on its right and \$0.5\$ on its left. This calculates \$\binom{1/2}{n}\$ for all \$n \in v\$.  
`*×` multiplies this vector element-wise with \$h^\prime \* n\$ (\$\*\$ denotes exponentiation).  
`×⍨` is commuted multiplication, which given only a right argument, seems to use this as left and right argument? and squares the vector element-wise.
[Answer]
# [Ruby](https://www.ruby-lang.org/), 63 bytes
```
->a,b,h=1r*(a-b)/a+=b{3.141593*a*((154+53*h*=h)*h*h/1e4+h/4+1)}
```
[Try it online!](https://tio.run/##VdC7boQwEAXQPl8xIg1Pw/iFXZAfQRQ2AnmjlRLxiBSxfDsxsGiVZop7Zm4xw2x/t77asg@T2tRVOMShyWyUm6SyCyPIUWgWmzgMUfBEsNjFlYv8dDl2PHE5TzBat/oNoMYUAPYhCVUMlWBF2aSHEJo@RVNRakQtLhGnlEQzWqIuL6FXmyZSKc4VpcUp7BJkhEmu/CE9RVxCkRRYFJwL/mwr9n0/tCT/25D6Pu4vhZBEMqE1k14a0pnWwQKP/TPtA77naYTAQAXvi1nTgNw/53EKdQQJBPaI7StWR9wf8Vj1tS9pXkr5wUN3N9Ptp4NuGL6GYzcc8zbDiBg7rgGs2x8 "Ruby – Try It Online")
A [direct port](https://tio.run/##VdC7asQwEAXQPl8xOI38kvW2tOD0KQLpzRaSsXHCQoIfgeD1tztaec2SZop7Zm4xw@x@t67a8hebueXNTv3p9P6aINRXfEiQzV2cJKywaeXiAlGSIpH3hfUhwTJObbxu9RNATTMAuA2FmeZUS07KcxYEs@wuhsnSUGrkIXKXEhvOSmrKQ9jRZrDSWgjNGNmFH0I55kpof8h2kYcwigklRAgp7m3ktu@HUfh/G2W@T/hLKRVWXBrDlZczbm3TwwJX/5SsucL3PI0QWajgebFrFuHL5zxOyMSQQuRC7B6xDnEX4rHqal9yfigTgYf2YqePnxbaYfgawi4aiyanMbZuXCNYtz8 "Ruby – Try It Online") of @Arnauld's [JavaScript answer](https://codegolf.stackexchange.com/a/211770/92901) is shorter (58 bytes). However, I like the 63-byter above because it differs from other approaches in that it's a cubic polynomial: no square roots, no infinite series.
[This excellent review](http://www.ebyte.it/library/docs/math05a/EllipsePerimeterApprox05.html) lists nearly 40 different methods for approximating the circumference of an ellipse, with graphs of the relative error in each approximation as a function of \$b/a\$. Inspection of the graphs shows that only a few of the listed methods are capable of satisfying the required tolerance of \$10^{-6}\$ for all test cases. Since several answers here had already explored 'Ramanujan II' (eq. (5)), I decided to look at the Padé approximations 'Padé 3/2' and 'Padé 3/3'.
A [Padé approximant](https://en.wikipedia.org/wiki/Pad%C3%A9_approximant) is a rational function with coefficients chosen so as to match the largest possible number of terms in a known power series. In this case, the relevant power series is the infinite sum that appears in eq. (4). The Padé 3/2 and Padé 3/3 approximants for this series are mathematically straightforward (see the review linked above) but not suited to code golf. Instead, an *approximation to the approximants* is obtained by least-squares fitting. The resulting cubic polynomial (with truncated coefficients), as implemented in the code, is
$$
0.0053h^3 + 0.0154h^2+0.25h+1.
$$
Note that this function is overfitted to the test cases, partly because of the truncation and partly because the fit was optimised using only those values of \$h=(a-b)^2/(a+b)^2\$ that occur in the test cases. (Consequently, `Math::PI` cannot be substituted in place of `3.141593`, despite having the same byte count, without yielding relative errors above the \$10^{-6}\$ threshold for the two test cases for which \$b/a=1/2\$.)
[Answer]
# x87 machine code, ~~65~~ ~~59~~ 53 bytes
```
00000000: d9c1 d9c1 dec1 d9ca dee9 d8c8 d9c1 d8c8  ................
00000010: def9 6a03 8bf4 de0c ff04 df04 d9c1 dee9  ..j.............
00000020: d9fa 8304 06de 04de f9d9 e8de c1d9 ebde  ................
00000030: c9de c95e c3                             ...^.
```
Listing:
```
D9 C1       FLD   ST(1)             ; load a to ST
D9 C1       FLD   ST(1)             ; load b to ST
DE C1       FADD                    ; a + b
D9 CA       FXCH  ST(2)             ; save result for end 
DE E9       FSUB                    ; a - b 
D8 C8       FMUL  ST(0), ST(0)      ; ST ^ 2 
D9 C1       FLD   ST(1)             ; copy a + b result to ST 
D8 C8       FMUL  ST(0), ST(0)      ; ST ^ 2 
DE F9       FDIV                    ; calculate h 
6A 03       PUSH  3                 ; load const 3 
8B F4       MOV   SI, SP            ; SI to top of CPU stack
DE 0C       FIMUL WORD PTR[SI]      ; ST = h * 3 
FF 04       INC   WORD PTR[SI]      ; 4 = 3 + 1 
DF 04       FILD  WORD PTR[SI]      ; load const 4 
D9 C1       FLD   ST(1)             ; load 3h to ST
DE E9       FSUB                    ; 4 - 3h 
D9 FA       FSQRT                   ; sqrt(ST) 
83 04 06    ADD   WORD PTR[SI], 6   ; 10 = 4 + 6 
DE 04       FIADD WORD PTR[SI]      ; ST + 10 
DE F9       FDIV                    ; 3h / ST 
D9 E8       FLD1                    ; load const 1 
DE C1       FADD                    ; ST + 1 
D9 EB       FLDPI                   ; load PI 
DE C9       FMUL                    ; * PI 
DE C9       FMUL                    ; * ( a + b ) from earlier 
5E          POP   SI                ; restore CPU stack 
C3          RET                     ; return to caller 
```
Callable function, input `a` and `b` in `ST(0)` and `ST(1)`. Output in `ST(0)`. Implements Ramanujan's 2nd approximation (eq 5) in full hardware 80-bit extended precision.
Test program:
[![enter image description here](https://i.stack.imgur.com/iP4N0.png)](https://i.stack.imgur.com/iP4N0.png)
[Answer]
# JavaScript (ES7), ~~59~~ 56 bytes
*Saved 2 bytes thanks to @DominicvanEssen*
```
a=>b=>Math.PI*((h=3*(a-b)**2/(a+=b))/(10+(4-h/a)**.5)+a)
```
[Try it online!](https://tio.run/##dc1NTsNADIbhPafI0pMonrE9np/FdM8CiStMSkuKqgbRiuuHIJCIUrHxwnr0vW/1s173H6f3W3@ZXg7zscy17Iaye6q3EZ8fW4CxSAu1H0zbsoXalcEYC@Q68P1o6/JGNV018366XKfzAc/TKxyBmsYsx5jG2iYgJ6Gk4uLDhiGvWWaNmSjrHdM/FjELR8rxjvE6mjGk5H1idhsma0aCEnxaJnnDdM2Y0JFz3qvfRt03c7/RgP9EicWA1x@mGjCI5ixh/gI "JavaScript (Node.js) – Try It Online")
[Answer]
# [J](http://jsoftware.com/), ~~31~~ 30 bytes
-1 byte thanks to Jonah!
```
[:o.1#.+*i.@9*:@(^~*0.5!~[)-%+
```
[Try it online!](https://tio.run/##fc6xCsJAEATQPl8xicjlLmbZu@TALAgBwcrKNmATDGqTP8ivn2cfthimeDDMN1VkFlwEBicwJKclXB/3W5pkJX@gxn1oHJyM9XNzTLHcJtsem2QLFK/5vcIwDQbnUgJqD2ABvM29oxRUjYoGdblTNaoa@K@e7e6p0GXsY8b0Aw "J – Try It Online")
Essentially a J port of [@ovs's APL solution](https://codegolf.stackexchange.com/a/211775/75681).
[Answer]
# [C (gcc)](https://gcc.gnu.org/), ~~97~~ ~~92~~ 91 bytes
Saved ~~4~~ 5 bytes thanks to [Dominic van Essen](https://codegolf.stackexchange.com/users/95126/dominic-van-essen)!!!  
Saved 2 bytes thanks to [ceilingcat](https://codegolf.stackexchange.com/users/52904/ceilingcat)!!!
```
float f(a,b,k)float a,b,k;{k=k?:2;k=k>999?1:(1-b*b/a/a)*(k-4+3/k)/k*f(a,b,k+2)+6.283185*a;}
```
[Try it online!](https://tio.run/##dZLbjpswEIbv8xSjSJE4GINtbPCyh4uqT9FEK0NMi0ghAi6iRnn2dDhksxu1CGyP/f3j32OK4GdRXK/loTUDlI4hOandOZrG2bl@qd@eeIbdq9b6jT05LMi9PDShcT2nDmJfhLUb1t6i9rnrK8pTwVLpmexyrZoBfpuqcdzVeQX4zOkH2w/v5scOXuDMCDDKx0YSwF4QGAcRznBxyR5V@V318KIill8E9nS0xWD3s@RmTEQJAUU1l4lmTONmCdWCJ0wnY6CpStM4TvlkQVCh4hSX0RlnNGJRFMcyRkzROyalokpIrYX6auDYV4e2wd1ZZAM1LxW/TOdBN5tab0/f@fakv@En1wQ@x2KNyeZsbQfOWMuq2dsT6qJsGT5DX/2xbenczuqGy4T3MZOB70@0C/Ml3A0azLVcxkTssgcgvwH5fwCLwEed/430iEw/iPu4sreHYbRQmrx3@sB@AsbTFm3XYWIEZvD5VtA7duwQLJ31piSwKSF4HdtNv22wloZATqAnWOsl027Z4LK6XP8C "C (gcc) – Try It Online")
Port of [Anders Kaseorg](https://codegolf.stackexchange.com/users/39242/anders-kaseorg)'s [Python answer](https://codegolf.stackexchange.com/a/211780/9481).
[Answer]
# [MathGolf](https://github.com/maxbergmark/mathgolf/blob/master/math_golf.txt), 20 [bytes](https://github.com/maxbergmark/mathgolf/blob/master/code_page.py)
```
-ëΣ_¬/²3*_4,√♂+/)π**
```
Port of [my 05AB1E answer](https://codegolf.stackexchange.com/a/211776/52210), and thus also implements a modification of the fifth formula.
[Try it online.](https://tio.run/##y00syUjPz0n7/1/38Opzi@MPrdE/tMlYK95E51HHrEczm7T1Nc83aGn9/2@oZ6AAxFyGekZQ2hRMG0HFjaG0KZQ2MgAxDEAqjUByJkAJAA)
**Explanation:**
```
-                     # b-a
 ëΣ                   # a+b
   _                  # Duplicate
    ¬                 # Rotate stack: b-a,a+b,a+b → a+b,b-a,a+b
     /                # Divide
      ²               # Square
       3*             # Multiply by 3
         _            # Duplicate
          4,          # Subtract from 4
            √         # Square-root
             ♂+       # Add 10
               /      # Divide
                )     # Increment by 1
                 π*   # Multiply by PI
                   *  # Multiply by the a+b we've duplicated
                      # (after which the entire stack is output implicitly as result)
```
[Answer]
# [Wolfram Language (Mathematica)](https://www.wolfram.com/wolframscript/), ~~25~~ 24 bytes
```
4EllipticE[1-(#2/#)^2]#&
```
[Try it online!](https://tio.run/##y00syUjNTSzJTE78n2b738Q1JyezAMhzjTbU1VA20lfWjDOKVVb7H1CUmVcSraxrl@bg4BetHBurpqDvoFBdbahjWKtTbahnBKVNwTSEZwwmoSIGOoYGIBVGxjomprW1//8DAA "Wolfram Language (Mathematica) – Try It Online")
-1 thanks to @AndersKaseorg
Note that Mathematica uses a different convention for elliptic integrals, hence the square root disappears.
[Answer]
# Haskell, 73 bytes
```
e a b=(a+b)*pi*(1+3*l/(10+sqrt(4-3*l))+3*l^5/2^17)where l=((a-b)/(a+b))^2
```
Experimenting with an improved version of (5):
$$E(a,b) = \pi (a+b) \left( 1 + \frac{3h^2}{10 + \sqrt{4-3h^2}} + \frac{3h^{10}}{2^{17}}\right)$$
[Answer]
# [MATL](https://github.com/lmendo/MATL "MATL – Try It Online"), 19 bytes
```
y/U_Q.5t_hlbZh*YPE*
```
[Try it online!](https://tio.run/##y00syfn/v1I/ND5Qz7QkPsMwKSpDKzLAVev/fyMuQwA) Or [verify all test cases](https://tio.run/##y00syfmf8L9SPzQ@UM@0JD7DMCkqQysywFXrv0vIf0MuINQzApOmQBLEMgZiMNuAyxCIjIy5TEwB).
### Formula used
This is based on formula (1) from the challenge description,
\[
C = 4a\int^{\pi/2}\_{0}{\sqrt{1-e^2 \sin^2 \theta} ;d\theta} = 4 a\,E(e),
\]
where \$e\$ is the eccentricity,
\[
e = \sqrt{1 - b^2/a^2},
\]
and \$E\$ is the [complete elliptic integral of the second kind](https://en.wikipedia.org/wiki/Elliptic_integral#Complete_elliptic_integral_of_the_second_kind). This integral can be expressed in terms of [Gauss' hypergeometric function](https://en.wikipedia.org/wiki/Hypergeometric_function), \${}\_2F\_1\$, as follows:
\[
E(e) = \tfrac{\pi}{2} \;{}\_2F\_1 \left(\tfrac12, -\tfrac12; 1; e^2 \right).
\]
Combining the above gives the formula used in the code:
\[
C = 2\pi a \;{}\_2F\_1 \left(\tfrac12, -\tfrac12; 1; 1 - b^2/a^2 \right).
\]
### Code explanation
```
y       % Implicit inputs: a, b. Duplicate from below
        % STACK: a, b, a
/       % Divide
        % STACK: a, b/a
U_Q     % Square, negate, add 1
        % STACK: a, 1-(b/a)^2
.5t_h   % Push 0.5, duplicate, negate, concatenate
        % STACK: a, 1-(b/a)^2, [0.5, -0.5]
1       % Push 1
        % STACK: a, 1-(b/a)^2, [0.5, -0.5], 1
b       % Bubble up in the stack
        % STACK: a, [0.5, -0.5], 1, 1-(b/a)^2
Zh      % Hypergeometric function, 2F1
        % STACK: a, 2F1([0.5, -0.5], 1, 1-(b/a)^2)
*       % Multiply
        % STACK: a * 2F1([0.5, -0.5], 1, 1-(b/a)^2)
YPE     % Push pi, multiply by 2
        % STACK: a * 2F1([0.5, -0.5], 1, 1-(b/a)^2), 2*pi
*       % Multiply. Implicit display
        % STACK: 2*pi*a * 2F1([0.5, -0.5], 1, 1-(b/a)^2)
```
[Answer]
# APL(NARS), 21 chars
```
a←⎕⋄{√+/×⍨a×1 2○⍵}∫○2
```
test:
```
      a←⎕⋄{√+/×⍨a×1 2○⍵}∫○2
⎕:
      1 1
6.283185307 
      a←⎕⋄{√+/×⍨a×1 2○⍵}∫○2
⎕:
      123 45
556.6359936 
```
it is based on the parametric representation of ellipse something as
`phi(t)=(a cos(t),b sin(t)) t∊[0,2π)`
and the formula for find the lenght of the curve $$L(\varphi)=\int\_0^{2\pi} \left| \varphi'(t) \right|dt $$
where `phi'(t)=(a -sin(t), b cos(t) ) t∊[0,2π)`.
It is possible calculate more digit in that integral but solution is more long, as in
```
      ⎕FPC←3000⋄a←⎕⋄300⍕{√+/×⍨a×1 2○⍵}∫○2v
⎕:
      1 1
 6.283185307179586476925286766559005768394338798750211641949889184615632812572417997256069650684234135964296173026564613
      294187689219101164463450718816256962234900568205403877042211119289245897909860763928857621951331866892256951296467
      573566330542403818291297133846920697220908653296426787214520498282547
      300⍕○2v
 6.283185307179586476925286766559005768394338798750211641949889184615632812572417997256069650684234135964296173026564613
      294187689219101164463450718816256962234900568205403877042211119289245897909860763928857621951331866892256951296467
      573566330542403818291297133846920697220908653296426787214520498282547
```
[Answer]
# [SageMath](https://sagemath.org), 37 bytes
```
lambda a,b:4*a*elliptic_ec(1-b*b/a/a)
```
[Try it online!](https://sagecell.sagemath.org/?z=eJw1jUEKgzAURPeB3OHvzA8xmlQ3QnuRtpSfVCGgVmx24t0b23Q278EMzHC-cTbS5J4EpFzXSJL9OIYlBv_ovTClk66iipAzzobXCp7ePYQZrsJoZTSqRPuX9ic2N6fMNtPWServ1KauaTXeO84gZVnDHEWx7VBeYNsLnb4miuK4UzAIeQgifgCCUywB&lang=sage&interacts=eJyLjgUAARUAuQ==)
Uses the elliptic integral formulation.
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), ~~22~~ ~~21~~ 20 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
ÆnIOn/3*D4s-tT+/>IOžqP
```
Implements the fifth formula. Input as a pair \$[a,b]\$.
-1 byte thanks to *@ovs*.
[Try it online](https://tio.run/##yy9OTMpM/f//cFuep3@evrGWi0mxbkmItr6dp//RfYUB//9Hm@oYxgIA) or [verify all test cases](https://tio.run/##yy9OTMpM/V9Waa@k8KhtkoKSfeX/w22V/vp5xlouJsW6JSHa@naV/kf3FQb81/kfHW2oYxirE22oZwSlTcE0hGcMJqEiBjqGBiAVRsY6JqaxsQA).
**Explanation:**
```
Æ                     # Reduce the (implicit) input-pair by subtraction: a-b
 IO                   # Push the input-pair again and sum it: a+b
   /                  # Divide them by one another: (a-b)/(a+b)
    n                 # Square it: ((a-b)/(a+b))²
     3*               # Multiply it by 3: ((a-b)/(a+b))²*3
       D              # Duplicate that
        4α            # Take the absolute difference with 4: |((a-b)/(a+b))²*3-4|
          t           # Take the square-root of that: sqrt(|((a-b)/(a+b))²*3-4|)
           T+         # Add 10: sqrt(|((a-b)/(a+b))²*3-4|)+10
             /        # Divide the duplicate by this:
                      #  (a-b)²/(a+b)²*3/(sqrt(|((a-b)/(a+b))²*3-4|)+10)
              >       # Increase it by 1:
                      #  (a-b)²/(a+b)²*3/(sqrt(|((a-b)/(a+b))²*3-4|)+10)+1
               IO     # Push the input-sum again: a+b
                 žq   # Push PI: 3.141592653589793
                   P  # Take the product of the three values on the stack:
                      #  ((a-b)²/(a+b)²*3/(sqrt(|((a-b)/(a+b))²*3-4|)+10)+1)*(a+b)*π
                      # (after which the result is output implicitly)
```
Note that I use \$\left|3h-4\right|\$ instead of \$4-3h\$ in my formula to save a byte, but given the constraints \$0<b\leq a\$, \$h\$ will be: \$0\leq h<1\$, and thus \$3h\$ will be at most \$2.999\dots\$.  
I also use \$h=\left(\frac{a-b}{a+b}\right)^2\$ instead of \$h=\frac{(a-b)^2}{(a+b)^2}\$ to save another byte (thanks to *@ovs*).
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 52 bytes
```
≧×χφＮθＮηＩ×⁴ΣＥＥφＥ²∕⁺ιλφ₂⁺××θθ⁻Σι⊗₂Πι××ηη⁻⁻²Σι⊗₂⁻⊕ΠιΣι
```
[Try it online!](https://tio.run/##bZC/bsIwEMbn5ilutCVXalA3pqosDFQIeAETX/BJiU2cmAHEs7t2nLZR1OWsz9/97l@lpausbELYyetH39PFHOiiB3aiFnsB5ZuAmq@Lrbn64cu3Z3SsW2gddUZZzL5HVVsHrObwKF4mY0M3Usi2pnLYohlQsY315ya@xHnqIQAjucgfp2AkYA6OQHbqREalErrYYN/4uMCx89Lhwdr8MVXMsRPQRXhHJhoo4GeiGaM4/@uWoxagf6kcV2n4f/nsz6dX46Y8103HehZ7R2Zgn7Kfzs7ek8P5OoQSyvB6a74B "Charcoal – Try It Online") Link is to verbose version of code. Works by approximating the line integral for a quadrant. The default precision is unfortunately only ~5 significant figures so the first four bytes are needed to increase the precision to ~7 significant figures. Further increases are possible for the same byte count but then it becomes too slow to demonstrate on TIO. Explanation:
```
≧×χφ
```
Increase the number of pieces \$ n \$ in which to divide the quadrant from \$ 1,000 \$ to \$ 10,000 \$. `≧×φφ` would increase it to \$ 1,000,000 \$ but that's too slow for TIO.
```
ＮθＮη
```
Input the ellipse's axes \$ a \$ and \$ b \$.
```
Ｉ×⁴Σ
```
After calculating the approximate arc length of each piece into which the quadrant was subdivided, take the sum, multiply by \$ 4 \$ for the whole ellipse and output the result.
```
ＥＥφＥ²∕⁺ιλφ
```
Create a list of pieces of the quadrant. In the ellipse equation \$ \left ( \frac x a \right ) ^ 2 + \left ( \frac y b \right ) ^ 2 = 1 \$ we can set \$ \left ( \frac {x\_i} a \right ) ^ 2 = \frac i n \$ and \$ \left ( \frac {y\_i} b \right ) ^ 2 = 1 - \frac i n \$. Given a piece index \$ i \$ we want to calculate the distance between \$ ( x\_i, y\_i ) \$ and \$ ( x \_{i+1}, y\_{i+1} ) \$. For each \$ i \$ we calculate \$ j = \frac i n \$ and \$ k = \frac {i+1} n \$ and loop over the list.
```
₂⁺××θθ⁻Σι⊗₂Πι××ηη⁻⁻²Σι⊗₂⁻⊕ΠιΣι
```
The distance \$ \sqrt { ( a \sqrt k - a \sqrt j ) ^ 2 + ( b \sqrt { 1 - j } - b \sqrt { 1 - k } ) ^ 2 } \$ expands to \$ 
\sqrt { a^2 \left ( j + k - 2 \sqrt { j k } \right ) + b^2 \left ( (1 - j) + (1 - k) - 2 \sqrt { (1 - j) (1 - k) } \right ) } \$ which expands to \$ 
\sqrt { a^2 \left ( j + k - 2 \sqrt { j k } \right ) + b^2 \left ( 2 - (j + k) - 2 \sqrt { 1 + j k - (j + k) } \right ) } \$.
[Answer]
# [APL (Dyalog Extended)](https://github.com/abrudz/dyalog-apl-extended), ~~28~~ 26 bytes
```
○+×1+∘(⊢÷10+∘√4-⊢)3×2*⍨-÷+
```
[Try it online!](https://tio.run/##SyzI0U2pTMzJT9dNrShJzUtJTfn//9H0bu3D0w21H3XM0HjUtejwdkMDEPtRxywTXSBf0/jwdCOtR70rdA9v1/6f9qhtwqPevkddzY961zzq3XJovfGjtomP@qYGBzkDyRAPz@D/hgppCoZchnpGUNoURAMA "APL (Dyalog Extended) – Try It Online")
ovs's conversion to a train.
-2 using `√`.
# [APL (Dyalog Extended)](https://github.com/abrudz/dyalog-apl-extended), 35 bytes
```
{h←3×2*⍨⍺(-÷+)⍵⋄(○⍺+⍵)×1+h÷10+√4-h}
```
[Try it online!](https://tio.run/##SyzI0U2pTMzJT9dNrShJzUtJTfn/vzrjUdsE48PTjbQe9a541LtLQ/fwdm3NR71bH3W3aDya3g0U0gbyNA9PN9TOOLzd0ED7UccsE92M2v9pQI2PevsedTU/6l3zqHfLofXGj9omPuqbGhzkDCRDPDyD/xsqpCkYchnqGUFpUzAN5gEA "APL (Dyalog Extended) – Try It Online")
Uses Equation 4.
Longer than the other APL answer because there's more than one usage of \$h\$.
[Answer]
# [Symja](https://symjaweb.appspot.com/), 35 bytes
```
f=N(4*#1*EllipticE(1-#2*#2/#1/#1))&
```
[Try It Online!](https://symjaweb.appspot.com/input?i=f%3dN%284%2a%231%2aEllipticE%281%2d%232%2a%232%2f%231%2f%231%29%29%26%3bf%2820%2c10%29)
A port of the SageMath answer in Symja.
[Answer]
# [Japt](https://github.com/ETHproductions/japt), 35 [bytes](https://en.wikipedia.org/wiki/ISO/IEC_8859-1)
```
MP*ºH=3*(U-V ²/(U±V)/(A+(4-H/U ¬ +U
```
[Try it](https://petershaggynoble.github.io/Japt-Interpreter/?v=1.4.6&code=TVAqukg9MyooVS1WILIvKFWxVikvKEErKDQtSC9VIKwgK1U&input=MTIzCjQ1)
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 20 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
I÷S²3×÷ạ4½+⁵Ʋ$‘×S×ØP
```
A monadic Link accepting a pair of `[a, b]` which yields the result of formula 5.
**[Try it online!](https://tio.run/##ATYAyf9qZWxsef//ScO3U8KyM8OXw7fhuqE0wr0r4oG1xrIk4oCYw5dTw5fDmFD///9bMTIzLCA0NV0 "Jelly – Try It Online")**
---
I thought formula 4 would be the way to go, but only got 21:
```
9Ḷ.c×⁹I÷S*⁸¤²ʋ€×ØP×SS
```
[Try it online!](https://tio.run/##ATgAx/9qZWxsef//OeG4ti5jw5figblJw7dTKuKBuMKkwrLKi@KCrMOXw5hQw5dTU////1sxMjMsIDQ1XQ "Jelly – Try It Online")
[Answer]
# [Pyth](https://github.com/isaacg1/pyth), 40 bytes
```
A,hQeQJc^-GH2^+GH2**.n0+GHhc*3J+T@-4*3J2
```
[Try it online!](https://tio.run/##K6gsyfj/31EnIzA10Cs5TtfdwyhOG0hoaenlGQAZGclaxl7aIQ66JkDa6P//aEM9Ix3DWAA "Pyth – Try It Online")
Just formula 5, like most other answers here.
[Answer]
# [Perl 5](https://www.perl.org/), 70 bytes
```
sub{my$s;map$s+=sqrt+($_[0]*cos)**2+($_[1]*sin)**2,0..1570795;4e-6*$s}
```
[Try it online!](https://tio.run/##TZBNj9owEIbv/hUW9ZIQghN/JTEh6vZSqepWPbQ9LQiFykGR@KoddouW7V@nttnS5DCe9/HMO@MclN6Iy9Eo@NCabjr90bUbGJjjNigBaqqLOa5etidkym19QGZcmV@6G4do@Zguop97M4oi6iVZRKbdORmnGBORp7kUJVeTLELm9VICN@K7ciO@7LUqwfYE7zurK2v8aA6btlvE/kjmuySezQK7AIHuu8YM04KRQrA0BwTTHpdU5JIQKSwXN55jyWhOpF0D0J6PxFlRcF5QmgLW44RhlvHCNlEgepwSnJI05VxwQFPPfZQZvvkQ6py4bxMiwxkTUrLszR/68UTgIhOcSSEBaPY69K8fvQB3uT2FqI7RKkbq92FU3aNl@cbRet9VQ9Rc70c3rLSuXPHEFfTpUqtNVa9M6ETi/Ur4zsK6a58UtHCvfflBt7sO/muBM/euKIKTDL6HwdfPEAZwCoOPHz49BGWvYQDr6m7CDFxdjzqxicCsgXaURYQY6HZ2GXbCbXpnc@6H@/WclM1/yTFV890AXH9X9cck4fzbeFT5mBg/uBnYKzQcxOqp3iBii87z5/F5jtDwvNaxStZKg9fLXw "Perl 5 – Try It Online")
# [Perl 5](https://www.perl.org/), 78 bytes
```
sub f{($a,$b)=@_;$H=3*(($a-$b)/($a+=$b))**2;3.141593*$a*(1+$H/(10+sqrt 4-$H))}
```
With the `a+=b` trick stolen from the Javascript answer.
[Try it online!](https://tio.run/##TZHbbtswDIbv9RRCqtaH2LJ1sq04xrqbIcM67GLbVRMEDiAHBnKa5bYrmuzVM0npMhsCRX4if9LgQXUbcX7SCj60up9MfvbtBnr6aeuVZ/20gs2bj@oIrYLqflmiWcVC34DYgMTc48o4QRjSkmHCiZAsRHXokzGaJT5Jx/pX10Meo1kQnM43Fz2u4iw0DeC2PqDlY7oIXRaJfXMMIIvEYSsbhLrdGWj9KMWYiDzNpTgBO/APZQf@uu9UCbav8L43cWVEH/Vh0/aLyF3JfJdE06nnlYBA@11shmnBSCFYmgOC6YBLKnJJiBSGiyvPsWQ0J9I0B3SgI3FWFJwXlKaADThhmGW8MEUUiAGnBKckTTkXHNDUcWdlhq86hFol7sqEyHDGhJQsA6DZd777y@AN2Mft62U3EVK/D2ZBaFm@c7Te91XzvrkrVF1X2dTYPg/pslObql5p3waJUyvhjYF13z4raOC@c@mHrt318F8JnNrpwxDGGfwAvW9fIPTgBHqfPn5@8MpBwQjW1W3MNFxdrjoxjsCsgaaVQYRoaCe2HraBnfTW@Nw1d@PZUDb/Q46pmu9GrguE1R@d@PPv46ByNtGucTMyT@huFKnneoOISTrOX8bHOUJ3x3UXqWStOnA6/wU "Perl 5 – Try It Online")
Or this one which is 13 bytes less (but uses core module List::Util)
# [Perl 5](https://www.perl.org/) -MList::Util=sum, ~~74~~ ~~65~~ 65+16 bytes
```
sub f{4e-6*sum map sqrt+($_[0]*cos)**2+($_[1]*sin)**2,0..1570795}
```
[Try it online!](https://tio.run/##TZDLbtswEEX3/IqBq0S2LFPiSxItC003BYqm6KLtKjYMuaAMAX6VlJMGcfrrLkmnrrQYzj0zc4fUQemNOB@NgvvWdNPpj67dQGiO27A8m@MKmheuJllkAWzrA5hfuhsPg@VDuoh@7s0oiqiXZBGZdudknGJMRJ7mUrx63@/K@X7Za1Wi7TPcdVZX1uvBHDZtt4j9kcx3STybhWGJCLjvEjNMC0YKwdIcEUx7XFKRS0KksFxceY4lozmRdjmiPR@Js6LgvKA0RazHCcMs44Udokj0OCU4JWnKueCIpp77KDN89SHUOXE/JkSGMyakZNmbP/j1ROAiE5xJIRFq9nroXz96Qa64fR4GdRys4kD9Poyqu2BZvvFgve@q5lIdXaHSunKtE1fu06VWm6pemaETiXcr4Z2Fddc@KrBwr337Qbe7Dv6NwMy9KopgksF7CL9@BghhCuHHD5/uw7I3MIC6upkwA6vLUSc2EZg1YFdZRIgBd2OXYSfcTW9szv1yfz0nZfNfckzVfDdAl59V/THJcP5tPKp8TIxf3AxsKbgdxOqx3gTENp3mT@PTPAhuT2sdq2StNHo9/wU "Perl 5 – Try It Online")
Which numerically calculates a variant of formula (1).
I was surprised this worked with sin and cos of integers up to 1570795 ≈ 500000π. But the tests in the question in "Try it online" has relative error < 0.000001. Guess `sin²(the integers)` is "averaged out" good enough.
[Answer]
# [CJam](https://sourceforge.net/p/cjam), 29 bytes
```
{_:+_P*@:-@d/_*3*_4\-mqA+/)*}
```
[Try it online!](https://tio.run/##S85KzP1fWPe/Ot5KOz5Ay8FK1yFFP17LWCveJEY3t9BRW19Tq/Z/3f9oUwXDWAA "CJam – Try It Online")
[Answer]
# [PARI/GP](https://pari.math.u-bordeaux.fr), 31 bytes
```
f(a,b)=4*a*ellE((1-b^2/a^2)^.5)
```
[Attempt This Online!](https://ato.pxeger.com/run?1=m728ILEoMz69YMGCpaUlaboW-9M0EnWSNG1NtBK1UnNyXDU0DHWT4oz0E-OMNOP0TDUhqm4WJhYU5FRqJCro2ikUFGXmlQCZSiCOkkJyYk6ORpqOQqKmpo5CdLShjoJhLJBhqGcEZ5lCWTARYygNFzcAMgzAao2AciamsbFQi2HOBAA)
[Answer]
# [Python](https://www.python.org)/[mpmath](https://mpmath.org), 51 bytes
```
lambda a,b:8*elliprg(0,a*a,b*b)
from mpmath import*
```
[Attempt This Online!](https://ato.pxeger.com/run?1=LYxNCsIwEEb3PcUsM2EsxqqUojdxk6CxgfwRxoVncRMQvZO3UVI378EH73u8853nFOvTHk-vG9vV-Bm8DuasQZOZRnnx3uVyFWvS8rdIg50tKUDIQfMMLuRUWP7Tg00FGFwEIRQpJKH6XfOmcd-4pQFx6iAXF1kwgRWSEZePWhd_AQ)
Using Carlson's symmetric integrals – as seen [here](https://codegolf.stackexchange.com/a/257775/110698) – not only removes the need to sort input, it saves 1 byte off the bog-standard \$4aE(e)\$ formula. As given in [DLMF 19.30.5](https://dlmf.nist.gov/19.30#E5), \$L=8R\_G(0,a^2,b^2)\$.
[Answer]
# [Arn](https://github.com/ZippyMagician/Arn), [22 bytes](https://github.com/ZippyMagician/Arn/wiki/Carn)
```
┴þ5‡Ôç¸„”R¤ËíÜç›WðÙÝÁ*
```
[Try it!](https://zippymagician.github.io/Arn?code=cGkqKDMqKCtcKS06LygqMys6fSkqKzMqOn0=&input=WzEgMV0KWzEuMiAxXQpbMiAxXQpbMjAgMTBd&flags=ZQ==) A pretty good approximation, but not exact for the larger values. Uses the crossed out formula (which I assume was removed due to the innacuracy). For any wondering, I managed to get the non-crossed out formula 5 to 33 bytes, but I couldn't figure out how to shorten it (and it was even less accurate than this one).
# Explained
Unpacked: `pi*(3*(+\)-:/(*3+:})*+3*:}`
```
pi                     Variable; first 20 digits of π
  *
    (
          3
        *
          (+\)         Folded sum ([a, b] -> a + b)
      -
        :/             Square root
            (
                  _    Variable; initialized to STDIN; implied
                *
                  3
              +
                  _    Implied
                :}     Tail
            )
          *
              _        Implied
            +
                3
              *
                  _    Implied
                :}
                       Ending parentheses implied
```
]