-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
10,430 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. | ||
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||
|
||
// See page 45. | ||
|
||
// (Package doc comment intentionally malformed to demonstrate golint.) | ||
//!+ | ||
package popcount | ||
|
||
// pc[i] is the population count of i. | ||
var pc [256]byte | ||
|
||
func init() { | ||
for i := range pc { | ||
pc[i] = pc[i/2] + byte(i&1) | ||
} | ||
} | ||
|
||
// PopCountExpression returns the population count (number of set bits) of x. | ||
func PopCountExpression(x uint64) int { | ||
return int(pc[byte(x>>(0*8))] + | ||
pc[byte(x>>(1*8))] + | ||
pc[byte(x>>(2*8))] + | ||
pc[byte(x>>(3*8))] + | ||
pc[byte(x>>(4*8))] + | ||
pc[byte(x>>(5*8))] + | ||
pc[byte(x>>(6*8))] + | ||
pc[byte(x>>(7*8))]) | ||
} | ||
|
||
// Ex 02.03 | ||
// PopCountLoop returns the population count (number of set bits) of x. | ||
func PopCountLoop(x uint64) int { | ||
var popCount byte | ||
for i := uint(0); i < 64; i += 8 { | ||
popCount += pc[byte(x>>i)] | ||
} | ||
return int(popCount) | ||
} | ||
|
||
// Ex 02.04 | ||
// PopCountLoop returns the population count (number of set bits) of x. | ||
func PopCountShift(x uint64) int { | ||
var popCount uint64 | ||
for x != 0 { | ||
popCount += x & 1 | ||
x = x >> 1 | ||
} | ||
return int(popCount) | ||
} | ||
|
||
// Ex 02.05 | ||
func PopCountClear(x uint64) int { | ||
var popCount int | ||
for x != 0 { | ||
x = x & (x - 1) | ||
popCount++ | ||
} | ||
return popCount | ||
} | ||
|
||
//!- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. | ||
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||
|
||
package popcount | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
// -- Benchmarks -- | ||
|
||
func BenchmarkPopCountExpression(b *testing.B) { | ||
for i := 0; i < b.N; i++ { | ||
PopCountExpression(0x1234567890ABCDEF) | ||
} | ||
} | ||
|
||
func BenchmarkPopCountLoop(b *testing.B) { | ||
for i := 0; i < b.N; i++ { | ||
PopCountLoop(0x1234567890ABCDEF) | ||
} | ||
} | ||
|
||
func BenchmarkPopCountShift(b *testing.B) { | ||
for i := 0; i < b.N; i++ { | ||
PopCountClear(0x1234567890ABCDEF) | ||
} | ||
} | ||
|
||
func BenchmarkPopCountClear(b *testing.B) { | ||
for i := 0; i < b.N; i++ { | ||
PopCountShift(0x1234567890ABCDEF) | ||
} | ||
} | ||
|
||
// Go 1.6, 2.67GHz Xeon | ||
// $ go test -cpu=4 -bench=. gopl.io/ch2/popcount | ||
// BenchmarkPopCount-4 200000000 6.30 ns/op | ||
// BenchmarkBitCount-4 300000000 4.15 ns/op | ||
// BenchmarkPopCountByClearing-4 30000000 45.2 ns/op | ||
// BenchmarkPopCountByShifting-4 10000000 153 ns/op | ||
// | ||
// Go 1.6, 2.5GHz Intel Core i5 | ||
// $ go test -cpu=4 -bench=. gopl.io/ch2/popcount | ||
// BenchmarkPopCount-4 200000000 7.52 ns/op | ||
// BenchmarkBitCount-4 500000000 3.36 ns/op | ||
// BenchmarkPopCountByClearing-4 50000000 34.3 ns/op | ||
// BenchmarkPopCountByShifting-4 20000000 108 ns/op | ||
// | ||
// Go 1.7, 3.5GHz Xeon | ||
// $ go test -cpu=4 -bench=. gopl.io/ch2/popcount | ||
// BenchmarkPopCount-12 2000000000 0.28 ns/op | ||
// BenchmarkBitCount-12 2000000000 0.27 ns/op | ||
// BenchmarkPopCountByClearing-12 100000000 18.5 ns/op | ||
// BenchmarkPopCountByShifting-12 20000000 70.1 ns/op |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. | ||
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||
|
||
// See page 58. | ||
//!+ | ||
|
||
// Surface computes an SVG rendering of a 3-D surface function. | ||
package main | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"math" | ||
"os" | ||
) | ||
|
||
const ( | ||
width, height = 600, 320 // canvas size in pixels | ||
cells = 100 // number of grid cells | ||
xyrange = 30.0 // axis ranges (-xyrange..+xyrange) | ||
xyscale = width / 2 / xyrange // pixels per x or y unit | ||
zscale = height * 0.4 // pixels per z unit | ||
angle = math.Pi / 6 // angle of x, y axes (=30°) | ||
) | ||
|
||
var sin30, cos30 = math.Sin(angle), math.Cos(angle) // sin(30°), cos(30°) | ||
|
||
func main() { | ||
if len(os.Args) > 1 { | ||
switch os.Args[1] { | ||
// case "eggcrate": | ||
// graph(eggcrate) | ||
// case "moguls": | ||
// graph(moguls) | ||
// case "saddle": | ||
// graph(saddle) | ||
default: | ||
graph(wave) | ||
} | ||
} | ||
graph(wave) | ||
} | ||
|
||
func graph(f func(i, j float64) (float64, error)) { | ||
fmt.Printf("<svg xmlns='http://www.w3.org/2000/svg' "+ | ||
"style='stroke: grey; fill: white; stroke-width: 0.7' "+ | ||
"width='%d' height='%d'>", width, height) | ||
for i := 0; i < cells; i++ { | ||
for j := 0; j < cells; j++ { | ||
ax, ay, err := corner(i+1, j, f) | ||
if err != nil { | ||
continue | ||
} | ||
bx, by, err := corner(i, j, f) | ||
if err != nil { | ||
continue | ||
} | ||
cx, cy, err := corner(i, j+1, f) | ||
if err != nil { | ||
continue | ||
} | ||
dx, dy, err := corner(i+1, j+1, f) | ||
if err != nil { | ||
continue | ||
} | ||
fmt.Printf("<polygon points='%g,%g %g,%g %g,%g %g,%g'/>\n", | ||
ax, ay, bx, by, cx, cy, dx, dy) | ||
} | ||
} | ||
fmt.Println("</svg>") | ||
} | ||
|
||
func corner(i, j int, f func(i, j float64) (float64, error)) (float64, float64, error) { | ||
// Find point (x,y) at corner of cell (i,j). | ||
x := xyrange * (float64(i)/cells - 0.5) | ||
y := xyrange * (float64(j)/cells - 0.5) | ||
|
||
// Compute surface height z. | ||
z, err := f(x, y) | ||
if err != nil { | ||
return x, y, err | ||
} | ||
|
||
// Project (x,y,z) isometrically onto 2-D SVG canvas (sx,sy). | ||
sx := width/2 + (x-y)*cos30*xyscale | ||
sy := height/2 + (x+y)*sin30*xyscale - z*zscale | ||
return sx, sy, nil | ||
} | ||
|
||
func wave(x, y float64) (float64, error) { | ||
r := math.Hypot(x, y) // distance from (0,0) | ||
r = math.Sin(r) / r | ||
if math.IsNaN(r) { | ||
return r, errors.New("Result is NaN") | ||
} | ||
if math.IsInf(r, 0) { | ||
return r, errors.New("Result overflows float64") | ||
} | ||
return r, nil | ||
} | ||
|
||
func eggcrate(x, y float64) (float64, error) { | ||
r := 4 * (math.Pow(math.Sin(x), 2) + math.Pow(math.Sin(y), 2)) | ||
// r := (x * x) + (y * y) + 25*(math.Pow(math.Sin(x), 2)+math.Pow(math.Sin(y), 2)) | ||
if math.IsNaN(r) { | ||
return r, errors.New("Result is NaN") | ||
} | ||
if math.IsInf(r, 0) { | ||
return r, errors.New("Result overflows float64") | ||
} | ||
return r, nil | ||
} | ||
|
||
//!- |
Oops, something went wrong.