fix: parse the chip generation so M4 and later report Hz (#36)
diff --git a/README.md b/README.md
index 399657a..333d7c8 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
 
 The `go-m1cpu` module is a library for inspecting Apple Silicon CPUs in Go.
 
-Use the `m1cpu` Go package for looking up the CPU frequency for Apple M1 and M2 CPUs.
+Use the `m1cpu` Go package for looking up the CPU frequency for Apple Silicon M-series CPUs, M1 and later.
 
 # Install
 
@@ -23,7 +23,7 @@
 
 # Example
 
-Simple Go program to print Apple Silicon M1/M2 CPU speeds.
+Simple Go program to print Apple Silicon CPU speeds.
 
 ```go
 package main
diff --git a/cpu.go b/cpu.go
index 382c004..858495d 100644
--- a/cpu.go
+++ b/cpu.go
@@ -145,7 +145,6 @@
 // }
 import "C"
 import (
-	"fmt"
 	"sync"
 )
 
@@ -231,13 +230,9 @@
 }
 
 func toHz(hz uint64) uint64 {
-	var gen int
-	// If this errors, fallback to default int value
-	fmt.Sscanf(ModelName(), "Apple M%", &gen)
-
 	// Starting with M4, Apple appears to report clock speed in Khz
 	// See https://github.com/exelban/stats/commit/3e056562b360c937b883725f14f3427d5401b6fe
-	if gen >= 4 {
+	if generation(ModelName()) >= 4 {
 		return hz * 1000
 	}
 	return hz
diff --git a/generation.go b/generation.go
new file mode 100644
index 0000000..75ed47a
--- /dev/null
+++ b/generation.go
@@ -0,0 +1,17 @@
+// Copyright (c) The M1CPU Authors
+// SPDX-License-Identifier: MPL-2.0
+
+package m1cpu
+
+import "fmt"
+
+// generation returns the chip generation from a model name such as
+// "Apple M4 Pro", or 0 when the name carries no generation.
+func generation(model string) int {
+	var gen int
+	// If this errors, fallback to default int value
+	if _, err := fmt.Sscanf(model, "Apple M%d", &gen); err != nil {
+		return 0
+	}
+	return gen
+}
diff --git a/generation_test.go b/generation_test.go
new file mode 100644
index 0000000..a6ebf8c
--- /dev/null
+++ b/generation_test.go
@@ -0,0 +1,32 @@
+// Copyright (c) The M1CPU Authors
+// SPDX-License-Identifier: MPL-2.0
+
+package m1cpu
+
+import (
+	"testing"
+
+	"github.com/shoenig/test/must"
+)
+
+func Test_generation(t *testing.T) {
+	cases := []struct {
+		model string
+		exp   int
+	}{
+		{model: "Apple M1", exp: 1},
+		{model: "Apple M1 Pro", exp: 1},
+		{model: "Apple M3 Max", exp: 3},
+		{model: "Apple M4", exp: 4},
+		{model: "Apple M4 Pro", exp: 4},
+		{model: "Apple M5", exp: 5},
+		{model: "Apple M10", exp: 10},
+		{model: "VirtualApple @ 2.50GHz", exp: 0},
+		{model: "", exp: 0},
+	}
+	for _, tc := range cases {
+		t.Run(tc.model, func(t *testing.T) {
+			must.Eq(t, tc.exp, generation(tc.model))
+		})
+	}
+}