forked from harpocrates/inline-rust
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathPi.hs
66 lines (55 loc) · 1.46 KB
/
Pi.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
{-# LANGUAGE TemplateHaskell, QuasiQuotes #-}
module Main where
import Language.Rust.Inline
import Data.Int
extendContext basic
extendContext functions
setCrateRoot [("rayon", "0.9")]
[rust|
extern crate rayon;
use rayon::prelude::*;
|]
-- | Approximate π using the first 'n' terms of the series.
--
-- \[
-- \frac{\pi}{4} = 1 - \frac{1}{3} + \frac{1}{5} - \frac{1}{7} + \frac{1}{9} - \cdots
-- \]
piApprox :: Int64 -> Double
piApprox x = [rust|
f64 {
let mut approximation = 0.0;
let mut multiplier = 1.0;
for i in 0..$(x: i64) {
approximation += multiplier / (2 * i + 1) as f64;
multiplier *= -1.0;
}
4.0 * approximation
}
|]
-- | Approximate π up to 'n' hex decimal points using the Bailey–Borwein–Plouffe formula.
--
-- \[
-- \pi = \sum_{k=0}^\infty \frac{1}{16^k} \cdot \left(
-- \frac{4}{8k + 1} - \frac{2}{8k + 4} - \frac{1}{8k + 5} - \frac{1}{8k + 6}
-- \right)
-- \]
--
-- Do this in parallel using `rayon`!
piBbpRayon :: Int32 -> Double
piBbpRayon n = [rust|
f64 {
(0 .. $(n: i32))
.into_par_iter()
.map(|k| {
let a = 4.0 / (8*k + 1) as f64;
let b = 2.0 / (8*k + 4) as f64;
let c = 1.0 / (8*k + 5) as f64;
let d = 1.0 / (8*k + 6) as f64;
(a - b - c - d) / f64::powi(16.0, k)
})
.sum()
}
|]
main = do
putStrLn $ "π (alternating) ~ " ++ show (piApprox 10000)
putStrLn $ "π (BBP) ~ " ++ show (piBbpRayon 10)