Skip to content

Commit

Permalink
Exercises 03.12 - 04.02
Browse files Browse the repository at this point in the history
  • Loading branch information
ramfox committed Jan 6, 2018
1 parent 7ea4ed0 commit 32f4105
Show file tree
Hide file tree
Showing 9 changed files with 10,430 additions and 0 deletions.
62 changes: 62 additions & 0 deletions ex02.03-02.05/popcount.go
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
}

//!-
55 changes: 55 additions & 0 deletions ex02.03-02.05/popcount_test.go
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
114 changes: 114 additions & 0 deletions ex03.01-03.04/main.go
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
}

//!-
Loading

0 comments on commit 32f4105

Please sign in to comment.