math: add J1, Y1, Jn and Yn (Bessel functions)

Also amend j0.go (variable name conflict, small corrections).

R=rsc
CC=golang-dev
https://golang.org/cl/769041
diff --git a/src/pkg/math/all_test.go b/src/pkg/math/all_test.go
index 4b0aec6..2f133f1 100644
--- a/src/pkg/math/all_test.go
+++ b/src/pkg/math/all_test.go
@@ -310,6 +310,42 @@
 	3.252650187653420388714693e-01,
 	-8.72218484409407250005360235e-03,
 }
+var j1 = []float64{
+	-3.251526395295203422162967e-01,
+	1.893581711430515718062564e-01,
+	-1.3711761352467242914491514e-01,
+	3.287486536269617297529617e-01,
+	1.3133899188830978473849215e-01,
+	3.660243417832986825301766e-01,
+	-3.4436769271848174665420672e-01,
+	4.329481396640773768835036e-01,
+	5.8181350531954794639333955e-01,
+	-2.7030574577733036112996607e-01,
+}
+var j2 = []float64{
+	5.3837518920137802565192769e-02,
+	-1.7841678003393207281244667e-01,
+	9.521746934916464142495821e-03,
+	4.28958355470987397983072e-02,
+	2.4115371837854494725492872e-01,
+	4.842458532394520316844449e-01,
+	-3.142145220618633390125946e-02,
+	4.720849184745124761189957e-01,
+	3.122312022520957042957497e-01,
+	7.096213118930231185707277e-02,
+}
+var jM3 = []float64{
+	-3.684042080996403091021151e-01,
+	2.8157665936340887268092661e-01,
+	4.401005480841948348343589e-04,
+	3.629926999056814081597135e-01,
+	3.123672198825455192489266e-02,
+	-2.958805510589623607540455e-01,
+	-3.2033177696533233403289416e-01,
+	-2.592737332129663376736604e-01,
+	-1.0241334641061485092351251e-01,
+	-2.3762660886100206491674503e-01,
+}
 var lgamma = []fi{
 	fi{3.146492141244545774319734e+00, 1},
 	fi{8.003414490659126375852113e+00, 1},
@@ -514,6 +550,42 @@
 	4.8290004112497761007536522e-01,
 	2.7036697826604756229601611e-01,
 }
+var y1 = []float64{
+	0.15494213737457922210218611,
+	-0.2165955142081145245075746,
+	-2.4644949631241895201032829,
+	0.1442740489541836405154505,
+	0.2215379960518984777080163,
+	0.3038800915160754150565448,
+	0.0691107642452362383808547,
+	0.2380116417809914424860165,
+	-0.20849492979459761009678934,
+	0.0242503179793232308250804,
+}
+var y2 = []float64{
+	0.3675780219390303613394936,
+	-0.23034826393250119879267257,
+	-16.939677983817727205631397,
+	0.367653980523052152867791,
+	-0.0962401471767804440353136,
+	-0.1923169356184851105200523,
+	0.35984072054267882391843766,
+	-0.2794987252299739821654982,
+	-0.7113490692587462579757954,
+	-0.2647831587821263302087457,
+}
+var yM3 = []float64{
+	-0.14035984421094849100895341,
+	-0.097535139617792072703973,
+	242.25775994555580176377379,
+	-0.1492267014802818619511046,
+	0.26148702629155918694500469,
+	0.56675383593895176530394248,
+	-0.206150264009006981070575,
+	0.64784284687568332737963658,
+	1.3503631555901938037008443,
+	0.1461869756579956803341844,
+}
 
 // arguments and expected results for special cases
 var vfacoshSC = []float64{
@@ -847,6 +919,24 @@
 	0,
 	NaN(),
 }
+var j1SC = []float64{
+	0,
+	0,
+	0,
+	NaN(),
+}
+var j2SC = []float64{
+	0,
+	0,
+	0,
+	NaN(),
+}
+var jM3SC = []float64{
+	0,
+	0,
+	0,
+	NaN(),
+}
 
 var vflgammaSC = []float64{
 	Inf(-1),
@@ -1042,6 +1132,24 @@
 	0,
 	NaN(),
 }
+var y1SC = []float64{
+	NaN(),
+	Inf(-1),
+	0,
+	NaN(),
+}
+var y2SC = []float64{
+	NaN(),
+	Inf(-1),
+	0,
+	NaN(),
+}
+var yM3SC = []float64{
+	NaN(),
+	Inf(1),
+	0,
+	NaN(),
+}
 
 func tolerance(a, b, e float64) bool {
 	d := a - b
@@ -1065,10 +1173,6 @@
 	switch {
 	case IsNaN(a) && IsNaN(b):
 		return true
-	case IsInf(a, 1) && IsInf(b, 1):
-		return true
-	case IsInf(a, -1) && IsInf(b, -1):
-		return true
 	case a == b:
 		return true
 	}
@@ -1409,6 +1513,38 @@
 	}
 }
 
+func TestJ1(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := J1(vf[i]); !close(j1[i], f) {
+			t.Errorf("J1(%g) = %g, want %g\n", vf[i], f, j1[i])
+		}
+	}
+	for i := 0; i < len(vfj0SC); i++ {
+		if f := J1(vfj0SC[i]); !alike(j1SC[i], f) {
+			t.Errorf("J1(%g) = %g, want %g\n", vfj0SC[i], f, j1SC[i])
+		}
+	}
+}
+
+func TestJn(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		if f := Jn(2, vf[i]); !close(j2[i], f) {
+			t.Errorf("Jn(2, %g) = %g, want %g\n", vf[i], f, j2[i])
+		}
+		if f := Jn(-3, vf[i]); !close(jM3[i], f) {
+			t.Errorf("Jn(-3, %g) = %g, want %g\n", vf[i], f, jM3[i])
+		}
+	}
+	for i := 0; i < len(vfj0SC); i++ {
+		if f := Jn(2, vfj0SC[i]); !alike(j2SC[i], f) {
+			t.Errorf("Jn(2, %g) = %g, want %g\n", vfj0SC[i], f, j2SC[i])
+		}
+		if f := Jn(-3, vfj0SC[i]); !alike(jM3SC[i], f) {
+			t.Errorf("Jn(-3, %g) = %g, want %g\n", vfj0SC[i], f, jM3SC[i])
+		}
+	}
+}
+
 func TestLdexp(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
 		if f := Ldexp(frexp[i].f, frexp[i].i); !veryclose(vf[i], f) {
@@ -1654,6 +1790,40 @@
 	}
 }
 
+func TestY1(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := Fabs(vf[i])
+		if f := Y1(a); !soclose(y1[i], f, 2e-14) {
+			t.Errorf("Y1(%g) = %g, want %g\n", a, f, y1[i])
+		}
+	}
+	for i := 0; i < len(vfy0SC); i++ {
+		if f := Y1(vfy0SC[i]); !alike(y1SC[i], f) {
+			t.Errorf("Y1(%g) = %g, want %g\n", vfy0SC[i], f, y1SC[i])
+		}
+	}
+}
+
+func TestYn(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := Fabs(vf[i])
+		if f := Yn(2, a); !close(y2[i], f) {
+			t.Errorf("Yn(2, %g) = %g, want %g\n", a, f, y2[i])
+		}
+		if f := Yn(-3, a); !close(yM3[i], f) {
+			t.Errorf("Yn(-3, %g) = %g, want %g\n", a, f, yM3[i])
+		}
+	}
+	for i := 0; i < len(vfy0SC); i++ {
+		if f := Yn(2, vfy0SC[i]); !alike(y2SC[i], f) {
+			t.Errorf("Yn(2, %g) = %g, want %g\n", vfy0SC[i], f, y2SC[i])
+		}
+		if f := Yn(-3, vfy0SC[i]); !alike(yM3SC[i], f) {
+			t.Errorf("Yn(-3, %g) = %g, want %g\n", vfy0SC[i], f, yM3SC[i])
+		}
+	}
+}
+
 // Check that math functions of high angle values
 // return similar results to low angle values
 func TestLargeCos(t *testing.T) {
@@ -1896,6 +2066,18 @@
 	}
 }
 
+func BenchmarkJ1(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		J1(2.5)
+	}
+}
+
+func BenchmarkJn(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Jn(2, 2.5)
+	}
+}
+
 func BenchmarkLdexp(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		Ldexp(.5, 2)
@@ -2020,3 +2202,15 @@
 		Y0(2.5)
 	}
 }
+
+func BenchmarkY1(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Y1(2.5)
+	}
+}
+
+func BenchmarkYn(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Yn(2, 2.5)
+	}
+}