ãããããªæ°å¦é¢æ°ãã¡ã® correct rounding ãªå®è£
ããã¦ãããã¨ããéã³ã§ãã
丸ãæ¹åã«ã¤ãã¦ã¯ä¸æ¦ã¯ tiesToEven ã®ã¿ãèãã¦ãã¾ãã
$\sin$ ã $\log$ ã®ãããªè¶
è¶é¢æ° (transcendental functions) ã¯å¤§å¤ã§ã¯ããã¾ããããã¾ãã¾ãªå
¸åãã¯ãããã®ã§ããã®ãã¡ç´¹ä»ãããã¨ã«ãªãã¨æãã¾ãã
ä»åã¯ãç¹ã«æ´ç·´ããã¦ããªãæ¹æ³ãç¨ã㦠$\sqrt{x}$ ã® correctly-rounded ãªå¤ãå¾ã¾ãããã¨ããåã§ãã
åæ
ç«å ´
ããã§ã¯ correct rounding ã§ãããã¨ãä¸çªã«éè¦è¦ãã¾ããããªãã¡ãçã®å¤ã $f(x)$ ã®ã¨ãããããæ£ç¢ºã«ä¸¸ããå¤ã欲ããã§ãã
ãããã調ã¹ãã¨ããããã®åéã§ã¯ $\roundcirc{f(x)}$ ã¨æ¸ããã¨ãå¤ãããªã®ã§ãããã§ããããã¾ã*1ãä»ã¾ã§ã®è¨äºã§ $\roundp{f(x)}$ ã®ããã«æ¸ãã¦ãããã®ã¨åãã§ãã
åãã¦ã®äººããããã¨ãæ£ç¢ºã«ä¸¸ãããã¨ããã®ãæ
£ããªãæ¦å¿µãããããªãã®ã§ãä¸å¿å
·ä½ä¾ãåºãã¦ããã¾ãã$\roundcirc{\sqrt2}$ ãèãã¾ãã
$$
\sqrt{2} = {\small 1.}{\footnotesize 414213562373095}{\scriptsize 048801688724209}{\tiny 698078569671875}{\tiny 376948073176679{\dots}}
$$
ã§ãbinary64 ã§è¡¨ããæ°ã®ãã¡ã$\sqrt{2}$ 以ä¸ã§æ大ã®ãã®ã¨ $\sqrt{2}$ 以ä¸ã§æå°ã®ãã®ã¯ãããããä¸è¨ã®éãã§ãã
$$
\begin{aligned}
\texttt{16A09E667F3BCC}_{(16)}\times 2^{-52}
&= {\small 1.}{\footnotesize 414213562373094}{\scriptsize 923430016933707}{\tiny 520365715026855}{\tiny 46875}, \\
\texttt{16A09E667F3BCD}_{(16)}\times 2^{-52}
&= {\small 1.}{\footnotesize 414213562373095}{\scriptsize 145474621858738}{\tiny 828450441360473}{\tiny 6328125}.
\end{aligned}
$$
åè
ã¨ã®å·®ã¯ $1.253\times 10^{-16}$ ç¨åº¦ãå¾è
ã¨ã®å·®ã¯ $9.667\times 10^{-17}$ ç¨åº¦ã§ãããå¾è
ã®æ¹ãè¿ããããå¾è
ã«ä¸¸ãããããã¨ã«ãªãã¾ã*2ã
ããã§åè
ã«ä¸¸ãã¦ãã¾ããã®ã¯ correct ã¨ã¯èªãããã¾ããããªããè² æ¹åã¾ãã¯æ£æ¹åã§æãè¿ããã®ã®ã©ã¡ããï¼æ¹åã¯å¼æ°ã«ãã£ã¦å¤ãã£ã¦ããï¼ã«ä¸¸ãããã®ã¯ faithful rounding ã¨å¼ã°ãã¾ãã
note: $\sqrt{2}$ ã $\tfrac13$ ãªã©ãï¼äºé²æ³ã§ï¼ç¡éå°æ°ã¨ãªããã®ã°ãããæèãããã¡ã§ããã$(1+2^{-52})^2$ ã®ãããªæéå°æ°ã§ã丸ã誤差ã¯çãã¾ãã
å¿ç¨å
ã«ãã£ã¦ã¯ faithful rounding ã§ããã§ããããããããã¯ãã£ã¨ã©ãã«ãç¸å¯¾èª¤å·® $10^{-14}$ãã®ãããªã®ã§æºè¶³ã§ããç¶æ³ãå¤ã
ããã§ãããããããã§ã¯ããã§ã¯ãªãã¨ãããã¨ã§ããèªæã«è² ããã«ããã¾ãããã
ã¾ããæ£å½æ§ã®è¨¼æãéè¦è¦ãã¾ããããã¯æµ®åå°æ°ç¹åã«éã£ã話ã§ã¯ãªãã§ãããæªè¨¼æã®ã¢ã«ã´ãªãºã ã¯ä½¿ãæ°ãããªãã§ããããã
人éãæ°å¼ã§è¡ãã®ã主ã«ãªãã¨æãã¾ãããGappa ã Coq ãªã©ã®è¨¼ææ¯æ´ã·ã¹ãã ã使ããã¨ãè¦éã«å
¥ãã¦ãã¾ãã
é度ãéãã«è¶ãããã¨ã¯ãªãã§ãããäºã®æ¬¡ã§ãããã¨ããfaithfully-rounded ãªçµæ㯠0.01 ms ã§å¾ãããããcorrectly-rounded ãªçµæ㯠30 s ããããã¨ãã¦ããæã
㯠correct rounding ã«åºå·ãã¾ãã
æ£å½æ§ãä¿ã£ãã¾ã¾ã§é«éåãããã°ãã°ããã®ã§ãã£ã¦ãcorrect rounding ãæ¨ã¦ãã®ã¯è«å¤ã§ãã
correct rounding ã®çä¿¡è
ã«ãªã£ãã¨æã£ã¦ãã ããã
å
æµ®åå°æ°ç¹åã¨ã㦠binary64 (double
, f64
) ãèãã¾ãã丸ãã¢ã¼ãã¨ãã¦ã¯ tiesToEven ã ããä¸æ¦æ³å®ãã¾ãã
ããªããã£ãæ¼ç®
- å®æ°ãªãã©ã«
- NaN ã $\pm\infty$ ãå«ãå®æ°ã®çæ
- ããã表ç¾å士ã®å¤æ (transmute)
f64
ãã u64
ã¸ã®ããã表ç¾ãä¿ã£ãå¤æ
u64
ãã f64
ã¸ã®ããã表ç¾ãä¿ã£ãå¤æ
- 128-bit 以ä¸ã®æ´æ°åï¼ç¬¦å·ãªãã符å·ã¤ãï¼ã®åæ¼ç®
- ååæ¼ç® (
+
, -
, *
, /
, %
)
/
ããã³ %
ã¯ãåã $0$ æ¹åã«ä¸¸ããåãæ¨ã¦é¤ç®ã¨ãã*3
- ãããæ¼ç® (
&
, |
, ^
, !
, <<
, >>
)
- æ¯è¼æ¼ç® (
==
, !=
, <
, >
, <=
, >=
)
- æµ®åå°æ°ç¹åã®åæ¼ç®
- ååæ¼ç® (
+
, -
, *
, /
)
- æ°å¼ä¸ã§ã¯ $\oplus$, $\ominus$, $\otimes$, $\oslash$ ã¨è¡¨è¨ãã
- fused multiply-add (FMA)
- $\roundcirc{x\times y + z}$ ã®ãã¨
- æ¯è¼æ¼ç® (
==
, !=
, <
, >
, <=
, >=
)
- NaN ã®å¤å®
æµ®åå°æ°ç¹åã®åæ¼ç®ã¯ correct rounding ã¨ãã¾ããå¾ã
ã«ãªã£ã¦ããæ´æ°åãªã©ã§ã¨ãã¥ã¬ã¼ãããæ¹æ³ãæ¸ãããããã¾ããããä¸æ¦ã¯ä¸ãããã¦ãããã®ã¨ãã¾ãã
ãã°ãã°æé»ã«è¡ãã¾ããã$2^{-1022}$ ã $2^{54}$ ã®ãããªå®æ°ã¯ãææ°é¢æ°ã®ãããªãã®ãæå³ãã¦ããã®ã§ã¯ãªããããã¾ã§å®æ°ãªãã©ã«ã«ç¸å½ãããã®ã¨ãã¦ä½¿ã£ã¦ãã¾ãã
ä¸è¨ã®æ¼ç®ã®ã¿ã§è¨ç®ã§ããã¢ã«ã´ãªãºã ãæ§æãããã®æ£å½æ§ã®è¨¼æã®éã«å¿
è¦ã§ããã°ç¡é精度ã®å®æ°ã®æ¼ç®ãç¨ãã¾ããæ°å¼ä¸ã®è¨ç®ã¯ã丸ã $\roundcirc{\bullet}$ ãæ示ããªãéãã¯ç¡é精度ã§ï¼ã¨ããããã ã®å®æ°ã®æ¼ç®ã¨ãã¦ï¼è¡ãã¾ã*4ã
note: $x \oplus y$ ã®ãããªæµ®åå°æ°ç¹æ°ç¨ã®æ¼ç®åã¯ããªãã©ã³ãã® $x$ ã $y$ ãæµ®åå°æ°ç¹æ°ã¨ãã¦è¡¨ããå¤ã§ããå ´åã®ã¿ä½¿ãæ³å®ã§ãããããããåæ㧠$\roundcirc{x+y}$ ã®ç¥è¨ã ã¨æã£ã¦å·®ãæ¯ããªãã§ãã
æ¬é¡
ããã¾ãããã
frexp
ã¾ã㯠frexp
ã¨å¼ã°ããé¢æ°ãç¨æãã¦ããã¾ãããã
ä¸ããããæµ®åå°æ°ç¹åã®å¤ããfraction 㨠exponent ã«åããé¢æ°ã§ãã
å
·ä½çã«ã¯ãéé¶ãªæéå¤ $x$ ãä¸ããããã¨ããä¸è¨ãæºãããããªçµ $(x_m, x_e)$ ãè¿ãã¾ãã$x_m$ ã¯æµ®åå°æ°ç¹åã§ã$x_e$ ã¯ç¬¦å·ã¤ãæ´æ°åã§ãã
- $x_m\times 2^{x_e} = x$, and
- $|x_m|\in[0.5\lldot 1)$.
$x$ ãã¼ã ($0_{\pm}$) ã¾ã㯠NaNã$\pm\infty$ ã®ã¨ã㯠$(x, 0)$ ãè¿ããã¨ã«ãã¦ããã¾ãã
ã¼ãã®ç¬¦å·ã«ã¤ãã¦
æ£è² ã®ã¼ã +0.0
㨠-0.0
ããããã $0_+$, $0_-$ ã¨æ¸ãã¦ãã¾ãã$\roundcirc{0} = 0_+$ ã $-0_+ = 0_-$ ãªã©ãæãç«ã¡ã¾ãã
+0.0 == -0.0
ã§ãããè¨å·ã®æ¯è¼ã¨ããæå³ã§ $0_+ \ne 0_-$ ã¨ãã¦ããã¾ãã
ä¸è¨ã®è¨äºã§ãå¤å°è§¦ãã¦ãã¾ãã
rsk0315.hatenablog.com
誤差è©ä¾¡ã®éç¨ã§ã¯ã¼ãã®ç¬¦å·ã¯åé¡ã«ãªããªãã®ã§ãæ°å¼ä¸ã§ã¯åã« $0$ ã¨æ¸ãã¦ãããã¨ã«ãã¾ãã$\eod$
signaling NaN ã quiet NaN ã®åºå¥ãªã©ã«é¢ãã¦ã¯ãä¸æ¦æ°ã«ããªããã¨ã«ãã¦ããã¾ã*5ã
ããã表ç¾ãå¾ã¦ããææ°é¨ã調æ´ãã¾ããéæ£è¦æ°ã«æ³¨æãã¾ããããglibc ã®å®è£
ã§ã¯ $2^{54}\cdot x$ ã®ã±ã¼ã¹ã«å¸°çããã¦ãã¾ãã*6ã
å®è£
const TWO_P54: f64 = 18014398509481984.0;
fn frexp(x: f64) -> (f64, i32) {
let mut ix = x.to_bits();
let mut ex = (ix >> 52 & 0x7FF) as i32;
if ex != 0x7FF && x != 0.0 {
let mut e = ex - 1022;
if ex == 0 {
let x = x * TWO_P54;
ix = x.to_bits();
ex = 0x7FF & (ix >> 52) as i32;
e = ex - 1022 - 54;
}
ix = (ix & 0x800FFFFFFFFFFFFF_u64) | 0x3FE0000000000000_u64;
(f64::from_bits(ix), e)
} else {
(x, 0)
}
}
ldexp
ç¶ã㦠frexp
ã®éæä½ (load exponent) ãç¨æãã¦ããã¾ãããã$(x_m, x_e)$ ã«å¯¾ã㦠$\roundcirc{x_m\times 2^{x_e}}$ ãè¿ãã¾ãã
$x_e$ ã®ç¯å²æ¬¡ç¬¬ã§ã¯ overflow ã underflow ãèµ·ããã®ã§ $\circ$ ãæ示ãã¦ãã¾ããããã以å¤ã®ã±ã¼ã¹ã§ã¯èª¤å·®ã¯çãã¾ããã
å¼æ°ã¯ $x_m\in[0.5\lldot 1)$ ã§ããå¿
è¦ã¯ããã¾ããã
å®è£
const TWO_P54: f64 = 18014398509481984.0;
const TWO_PM54: f64 = 5.5511151231257827021181583404541015625e-17;
fn ldexp(mut x: f64, e: i32) -> f64 {
if !x.is_finite() || x == 0.0 {
return x;
}
let mut ix = x.to_bits();
let mut k = (ix >> 52 & 0x7FF) as i32;
if k == 0 {
x *= TWO_P54;
ix = x.to_bits();
k = (ix >> 52 & 0x7FF) as i32 - 54;
}
if e < -50000 {
return 0.0_f64.copysign(x);
}
if e > 50000 || k + e > 0x7FE {
return f64::INFINITY.copysign(x);
}
k += e;
if k > 0 {
let bits = (ix & 0x800FFFFFFFFFFFFF_u64) | (k as u64) << 52;
return f64::from_bits(bits);
}
if k <= -54 {
return 0.0_f64.copysign(x);
}
k += 54;
let bits = (ix & 0x800FFFFFFFFFFFFF_u64) | (k as u64) << 52;
f64::from_bits(bits) * TWO_PM54
}
sqrt
ãã¦ãããããæ¬é¡ã§ãã$\roundcirc{\sqrt{x}}$ ãæ±ãã¾ãã
ã¾ã correct rounding ãªå®è£
ã®å
¸åçãªãã¿ã¼ã³ã¨ãã¦ã次ã®ãããªæµããããã¾ãã
- range reduction
- å
¥åãä¸è¬ã®ã±ã¼ã¹ããç¹æ®ãªã±ã¼ã¹ã«å¸°çããã
- approximation
- ææã®é¢æ°ã«å¿ããææ³ãç¨ããç¹æ®ãªã±ã¼ã¹ã«ã¤ãã¦ã®çããæ±ãã
- reconstruction
- 2. ã®çµæãç¨ããå
ã
ã®å
¥åã«å¯¾ããçããæ±ãã
ä»åãããã«å¾ã£ã¦è¡ãã¾ããè² ã®æ°ã NaN ãªã©ã®ã±ã¼ã¹ã«ã¤ãã¦ã¯äºãå¦çãã¦ãããã¨ã«ãã¾ãã
ã¾ãã$\sqrt{0_{\pm}\vphantom{0^0}} = 0_{\pm}$ï¼è¤å·åé ï¼ã¨å®ç¾©ããã¦ããã®ã§ããããå
ã«å¦çãã¦ããã¾ãã
range reduction
$\sqrt{2^{2 x_e}\cdot x_m} = 2^{x_e}\cdot\sqrt{x_m\vphantom{2^2}}$ ã§ãããã¨ããã$x_m\in[1\lldot 4)$ ã®ã±ã¼ã¹ã«ã¤ãã¦èãã¾ãã
$\texttt{frexp}(x) = (x_m', x_e')$ ã«å¯¾ãã¦ä¸è¨ãè¡ããã¨ã§å¸°çã§ãã¾ãã
$$
(x_m, x_e) = \begin{cases}
(4x_m', x_e'-2), & \text{if }x_e' \equiv 0\pmod 2; \\
(2x_m', x_e'-1), & \text{if }x_e' \equiv 1\pmod 2.
\end{cases}
$$
approximation
æåã«ã$y\in[1\lldot 2)$ ã§ãã£ã¦ã$y\le \sqrt{x_m\vphantom{2^2}}\lt y+2^{-52}$ ã¨ãªããã®ãæ±ãã¾ãã
ããã¯ãäºåæ¢ç´¢ã®è¦é ã§ã以ä¸ã®æç¶ãã«ãã£ã¦å¯è½ã§ãã
- å
¥å: $x_m\in[1\lldot 4)$
- $y \gets 1$ ã§åæåããã
- $\Delta y \gets 0.5$ ã§åæåããã
- å $i \gets \angled{1, 2, \dots, 52}$ ã«ã¤ãã¦ä¸è¨ãè¡ãã
- $\roundcirc{(y\oplus\Delta y)\times(y\oplus\Delta y)+(-x_m)}\le 0$ ã§ããã°ä¸è¨ãè¡ãã
- $y\xgets{\oplus}\Delta y$ ã§æ´æ°ããã
- $\Delta y \xgets{\otimes} 0.5$ ã§æ´æ°ããã
- $y$ ãåºåãã
note: åã«ã¼ãã®å
é ã«ããã¦ã$\Delta y = 0.5^i$ ãæãç«ã¡ã¾ãã
Claim 1: ä»»æã®æµ®åå°æ°ç¹æ° $x\in[1\lldot 2)$, $y\in[1\lldot 2]$, $z\in[1\lldot 4)$ ã«å¯¾ãã$$x\times y\le z \iff \roundcirc{x\times y+(-z)}\le 0$$ãæãç«ã¤ã
Proof
ä»»æã®å®æ° $w$ ã«å¯¾ãã$\roundcirc{w}\le 0 \iff w\le 2^{-1075}$ ã§ããã
ãã£ã¦ã
$$ x\times y\le z \iff x\times y-z \le 2^{-1075} $$
ã示ãã
($\implies$): æããã
($\impliedby$): å¯¾å¶ $x\times y\gt z \implies x\times y-z \gt 2^{-1075}$ ã示ãã
ããæ´æ° $m_x\in[2^{52}\lldot 2^{54})$, $m_y\in[2^{52}\lldot 2^{53}]$, $m_z\in[2^{52}\lldot 2^{54})$ ãç¨ã㦠$x = m_x\times 2^{-52}$, $y = m_y\times 2^{-52}$, $z = m_z\times 2^{-52}$ ã¨è¡¨ããã
$$
\begin{aligned}
x\times y - z
&= (m_x\times 2^{-52})\times (m_y\times 2^{-52})-(m_z\times 2^{-52}) \\
&= (m_x\cdot m_y - m_z\cdot 2^{52})\times 2^{-104}
\end{aligned}
$$
ãã $x\times y-z$ 㯠$2^{-104}$ ã®åæ°ã§ããããã
$$x\times y\gt z\implies x\times y-z\ge 2^{-104}\gt 2^{-1075}. \quad\qed$$
ããªãã¡ã$\roundcirc{(y\oplus\Delta y)\times(y\oplus\Delta y)+(-x_m)}\le 0$ ã®é¨å㯠$(y\oplus\Delta y)^2\le x_m$ ã¨åå¤ã§ã*7ã
$y\oplus\Delta y = y+\Delta y\in[1\lldot 2)$ ã¯å¸¸ã«æãç«ã¡ã¾ãã
ã¾ãã$y$ ã $\Delta y$ ã®æ´æ°ã«éãã¦çãã誤差㯠$0$ ã§ãã
次ã«ã丸ãã®å¢çã«çã®å¤ãç¾ãããã¨ã¯ãªããã¨ã示ãã¾ãã
Claim 2: ä»»æã® $x_m$ ã«å¯¾ã㦠$y+2^{-53} \ne \sqrt{x_m\vphantom{2^2}}$ ãæãç«ã¤ã
Proof
èçæ³ã«ããã
ä¸è¨ã®æç¶ãã®çµæ $y+2^{-53} = \sqrt{x_m\vphantom{2^2}}$ ãªããããªæµ®åå°æ°ç¹æ°ã®çµ $(x_m, y)$ ãåå¨ããã¨ããã
ãã®ã¨ãã$x_m = (y+2^{-53})^2 = y^2+2^{-52}\cdot y+2^{-106}$ ã¨ãªãã
$y\in[1\lldot 2)$ ãã $y$ 㯠$2^{-52}$ ã®åæ°ã§ããã
$$
y^2+2^{-52}\cdot y + 2^{-106}
\equiv 2^{-106}
\not\equiv 0 \pmod{2^{-104}}
$$
ã¨ãªããä¸æ¹ã$x_m\in[1\lldot 4)$ ã§ãã£ãããã$x_m$ 㯠$2^{-52}$ ã®åæ°ã§ããã$x_m\equiv 0\pmod{2^{-104}}$ ã¨ãªãã$\qed$
ãã£ã¦ã$y+2^{-53}\lt \sqrt{x_m\vphantom{2^2}}$ ã§ããã° $y\oplus 2^{-52}$ ããããã§ãªããã° $y$ ã approximation step ã®çãã¨ãªãã¾ãã
éè² æ§ã¯æãããªã®ã§ã$(y+2^{-53})^2\lt x_m$ ã¨åå¤ã§ã*8ã
ããªãã¡ã$y^2+2^{-52}\cdot y+2^{-106}-x_m\lt 0$ ãå¤å®ã§ããã°ããã§ãã
Claim 3: ä»»æã®æµ®åå°æ°ç¹æ° $x\in[1\lldot 4)$ ããã³ $y\in[1\lldot 2)$ ã«å¯¾ãã$$y^2+2^{-52}\cdot y-x\lt -2^{-106} \iff y^2+2^{-52}\cdot y-x\lt 0$$ãæãç«ã¤ã
Proof
($\implies$): æããã
($\impliedby$): å¯¾å¶ $y^2+2^{-52}\cdot y-x\ge -2^{-106} \implies y^2+2^{-52}\cdot y-x\ge 0$ ã示ãã
ããæ´æ° $m_x\in[2^{52}\lldot 2^{54})$, $m_y\in[2^{52}\lldot 2^{53})$ ãç¨ã㦠$x = m_x\times 2^{-52}$, $y = m_y\times 2^{-52}$ ã¨è¡¨ããã
$$
\begin{aligned}
y^2+2^{-52}\cdot y-x
&= (m_y\times 2^{-52})^2 + 2^{-52}\cdot(m_y\times 2^{-52}) - (m_x\times 2^{-52}) \\
&= (m_y^2+m_y-m_x\cdot 2^{52})\times 2^{-104}
\end{aligned}
$$
ãã $y^2+2^{-52}\cdot y-x$ 㯠$2^{-104}$ ã®åæ°ã§ããããã
$$y^2+2^{-52}\cdot y-x\ge -2^{-106} \implies y^2+2^{-52}\cdot y-x\ge 0.\quad\qed$$
Claim 3 ãã $y^2+2^{-52}\cdot y-x_m\lt 0$ ãå¤å®ããã°ãããã¨ã«ãªãã¾ããã
ããªãã¡ã$y\times(y+2^{-52})\lt x_m$ ã§ãããã㯠Claim 1 ãã FMA ã§è¨ç®å¯è½ã§ãã
reconstruction
ãã¦ãããã¾ã§ã§ $\roundcirc{\sqrt{x_m\vphantom{2^2}}} = y$ ãå¾ããã¾ããã$\texttt{ldexp}(y, \tfrac{x_e}2)$ ãæçµçãªçãã§ãã
å®è£
const TWO_PM52: f64 = 2.220446049250313080847263336181640625e-16;
fn sqrt(x: f64) -> f64 {
if x < 0.0 {
return f64::NAN;
}
if x == 0.0 || x.is_infinite() || x.is_nan() {
return x;
}
let (x_m, x_e) = match frexp(x) {
(m, e) if e % 2 == 0 => (4.0 * m, e - 2),
(m, e) => (2.0 * m, e - 1),
};
assert_eq!(x_e % 2, 0);
assert!(1.0 <= x_m && x_m < 4.0);
let mut y = 1.0_f64;
let mut dy = 0.5;
for _ in 0..52 {
if (y + dy).mul_add(y + dy, -x_m) <= 0.0 {
y += dy;
}
dy *= 0.5;
}
if y.mul_add(y + TWO_PM52, -x_m) < 0.0 {
y += TWO_PM52;
}
let y = ldexp(y, x_e / 2);
assert_eq!(y, x.sqrt());
y
}
次åäºå
ã¨ãããã $\roundcirc{\sqrt{x}}$ ãè¨ç®å¯è½ã§ãããã¨ã¯ç¤ºãã¾ãããããããé· $p$ ã«å¯¾ã㦠$\Theta(p)$ æéã¨ããã®ã¯ã¡ãã£ã¨ã... ã¨ããã®ãæ£ç´ãªã¨ããã§ãã
ãã¨ãã° $\Theta(\log(p))$ æéãããã«ãªã£ã¦ããããããããã§ãããã
ã¨ãããã¨ã§ä¸æ¦å®é¨ãã¾ããã
ã¾ã $3$ 次ãããã®éæ³ã®å¤é
å¼ã§ãã£ããè¿ä¼¼å¤ï¼èª¤å·® $10^{-4}$ ãããï¼ãæ±ãã¦ãNewton æ³ã§ $2$ åãããå復ãããã¨ã1 ULP ãããã®èª¤å·®ã«åã¾ã£ã¦ããããï¼
1 ULPï¼ã¨ãããå®æ° ULPï¼ã«åã¾ããã¨ã示ããã®ã§ããã°ãä»åãã£ãããã«ä¸çå¼è©ä¾¡ãã¦è£æ£ããã°ããã§ããããã
éæ³ã®å¤é
å¼ã¯æ¬¡ã®ãããªæãã§ãã
$$
\begin{aligned}
f_0(x)
&= \left(\begin{matrix}
\roundcirc{0.371351660146978} \\
\roundcirc{0.784942635287931} \\
\roundcirc{-0.180689144911217} \\
\roundcirc{0.0244769088312593}
\end{matrix}\right)^{\top}\cdot\left(\begin{matrix}
x^0 \\ x^1 \\ x^2 \\ x^3
\end{matrix}\right), \\
f_1(x)
&= \left(\begin{matrix}
\roundcirc{0.525170554189621} \\
\roundcirc{0.555038260254535} \\
\roundcirc{-0.0638832598267602} \\
\roundcirc{0.00432694705426709}
\end{matrix}\right)^{\top}\cdot\left(\begin{matrix}
x^0 \\ x^1 \\ x^2 \\ x^3
\end{matrix}\right). \\
\end{aligned}
$$
$f_0$ 㯠$[1\lldot 2)$ ç¨ã$f_1$ 㯠$[2\lldot 4)$ ç¨ã§ãã
å復㯠$y \xgets{\oplus} (x_m\oslash y)$ 㨠$y\xgets{\otimes} 0.5$ ã§ãã
ä¸è¨ã¯ $\sqrt{2}$ ãæ±ãããã¨ãã¦ããã¨ããã®ã¤ã¡ã¼ã¸ã§ãã
fn main() {
let poly = |x: f64| {
let mut y = 0.00432694705426709_f64;
y = y.mul_add(x, -0.0638832598267602);
y = y.mul_add(x, 0.555038260254535);
y.mul_add(x, 0.525170554189621)
};
let iter = |x: f64, y: f64| (y + x / y) * 0.5;
let x = 2.0;
let y = poly(x);
let y = iter(x, y);
let y = iter(x, y);
let y = iter(x, y);
}
åæå¤ãéæ³ã§æ±ºããã« $1$ ã¨ãããå§ãã¦ã $6$ åç¨åº¦ã§åæãã¦ããã¦ãããã§ããã
disclaimer: ãã³ã¡ããã¯æ°åå±ãããªã®ã§ããã®éãã«é²ã¾ãªãããããã¾ããã
ã¨ãããã hypot
, cbrt
, log
, exp
, sin
, cos
ããããããã¾ã§ã«é£½ããªãã¨ããã§ãããé çªã¯æªå®ã§ãã
ãã¾ã
äºåæ¢ç´¢ããã®ã§ããã°ãf64
ã使ããªãæ¹æ³ããã£ã¦ããã¨ãã° u128
ãªã©ã使ããªããæ´æ°ã¨ãã¦äºåæ¢ç´¢ãã¦ãããã§ãããã
æ´æ° $m_x\in[2^{52}\lldot 2^{54})$, $m_y\in[2^{52}\lldot 2^{53})$ ã§ãã£ã¦
$$ (m_y-\tfrac12)\times 2^{-52} \lt \sqrt{m_x\times 2^{-52}} $$
ãªã $y$ãããªãã¡
$$
\begin{aligned}
m_y-\tfrac12 &\lt 2^{52-26}\cdot\sqrt{m_x\mathstrut} \\
\Floor{(2m_y-1)^2\times 2^{-54}} &\lt m_x
\end{aligned}
$$
ãæºãããã㪠$m_y$ ã®æ大å¤ãæ±ããã°ããã§ãã
fn sqrt(x: f64) -> f64 {
assert_eq!(x_e % 2, 0);
assert!(1.0 <= x_m && x_m < 4.0);
let m_x = {
let mant = (1 << 52 | x_m.to_bits() & !(!0 << 52)) as u128;
if x_m >= 2.0 { 2 * mant } else { mant }
};
let m_y = {
let mut lo = 1_u128 << 52;
let mut hi = 2 * lo;
while hi - lo > 1 {
let mid = lo + (hi - lo) / 2;
let too_lo = (2 * mid - 1) * (2 * mid - 1) >> 54 < m_x;
*(if too_lo { &mut lo } else { &mut hi }) = mid;
}
lo as u64
};
let y = f64::from_bits(0x3FF << 52 | (m_y & !(!0 << 52)));
ldexp(y, x_e / 2)
}
ã¾ããä¸è¨ã®è¨äºã® Corollary 10 㨠u128::isqrt
ãç¨ãããã¨ã§ããã£ã¨ç°¡åã«æ±ãããã¨ãã§ãã¾ãã
rsk0315.hatenablog.com
fn sqrt(x: f64) -> f64 {
let m_x_p52 = m_x << 52;
let m_y = m_x_p52.isqrt();
let m_y = (if m_y * (m_y + 1) < m_x_p52 { m_y + 1 } else { m_y }) as u64;
let y = f64::from_bits(0x3FF << 52 | (m_y & !(!0 << 52)));
ldexp(y, x_e / 2)
}
ãããã¦ãu128
㧠$\floor{\sqrt{x_m\mathstrut}\times 2^{104}}$ ãæ±ãããã¨ãã§ããã°ãããã使ã£ãå®æ°åã®æ¼ç®ã§ f64
ã§ã® $\roundcirc{\sqrt{x_m\mathstrut}}$ ãæ±ãããããã¨ãããã£ã¦ãã¾ãã¾ããã
Rust ã® isqrt
ã§ã¯ãKaratsuba square root algorithm ãç¨ãã¦ãããã ([src]) ã§ãã競ãã er ã«ã¯ãã¾ã馴æã¿ã®ãªãã¢ã«ã´ãªãºã ãªã®ã§ã¯ãªãã§ãããã*9ã
ææ
ãããããçµå±ãæ´æ°åã§ãªãã¨ããªãããããã¨ããä¾ãåºã¦ãã¾ãããããã§ããã£ãã®ã...ï¼ãã¨ããæ°æã¡ã§ãã
ãã¡ããããããªã®ã¯ããããsqrt
ã®ãããªç°¡å㪠algebraic ãªé¢æ°ã ããã§ãããã¨ã§ãä»å¾ã® transcendental ãªé¢æ°ã§ã¯ããã¯ãããªãã¨æã£ã¦ãã¾ãã
次åã¯ãããã«åãã¦è«¸ã
ã®å
¸åãã¯ãå°å
¥ããã¯ãã§ãã
ããã
ãããã§ãã