From 4adc418d15411dc333cccd143f86e5f005c2cf2d Mon Sep 17 00:00:00 2001 From: Pierre Fenoll Date: Sat, 12 Oct 2024 17:02:36 +0200 Subject: [PATCH 1/2] fix(vet): use keyed fields for struct literal Signed-off-by: Pierre Fenoll --- primitive/raster.go | 2 +- primitive/util.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/primitive/raster.go b/primitive/raster.go index a5d620a..3870732 100644 --- a/primitive/raster.go +++ b/primitive/raster.go @@ -10,7 +10,7 @@ func fix(x float64) fixed.Int26_6 { } func fixp(x, y float64) fixed.Point26_6 { - return fixed.Point26_6{fix(x), fix(y)} + return fixed.Point26_6{X: fix(x), Y: fix(y)} } type painter struct { diff --git a/primitive/util.go b/primitive/util.go index 83446cd..1618dc2 100644 --- a/primitive/util.go +++ b/primitive/util.go @@ -61,7 +61,7 @@ func SaveJPG(path string, im image.Image, quality int) error { return err } defer file.Close() - return jpeg.Encode(file, im, &jpeg.Options{quality}) + return jpeg.Encode(file, im, &jpeg.Options{Quality: quality}) } func SaveGIF(path string, frames []image.Image, delay, lastDelay int) error { From e8310eaae89a97e48206bd13887fd115f0d0f796 Mon Sep 17 00:00:00 2001 From: Pierre Fenoll Date: Sat, 12 Oct 2024 17:26:00 +0200 Subject: [PATCH 2/2] feat: support passing a seed in for reproducibility Signed-off-by: Pierre Fenoll --- main.go | 12 ++++++++++-- primitive/model.go | 4 ++-- primitive/worker.go | 5 ++--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/main.go b/main.go index 59e3345..e7f4148 100644 --- a/main.go +++ b/main.go @@ -28,6 +28,7 @@ var ( Workers int Nth int Repeat int + Seed int64 V, VV bool ) @@ -73,6 +74,10 @@ func init() { flag.IntVar(&Workers, "j", 0, "number of parallel workers (default uses all cores)") flag.IntVar(&Nth, "nth", 1, "save every Nth frame (put \"%d\" in path)") flag.IntVar(&Repeat, "rep", 0, "add N extra shapes per iteration with reduced search") + flag.Func("seed", "seed to feed the RNG", func(value string) (err error) { + Seed, err = strconv.ParseInt(value, 10, 64) + return + }) flag.BoolVar(&V, "v", false, "verbose") flag.BoolVar(&VV, "vv", false, "very verbose") } @@ -126,7 +131,10 @@ func main() { } // seed random number generator - rand.Seed(time.Now().UTC().UnixNano()) + if Seed == 0 { + Seed = time.Now().UTC().UnixNano() + } + rand.Seed(Seed) // determine worker count if Workers < 1 { @@ -153,7 +161,7 @@ func main() { } // run algorithm - model := primitive.NewModel(input, bg, OutputSize, Workers) + model := primitive.NewModel(input, bg, OutputSize, Workers, Seed+1) primitive.Log(1, "%d: t=%.3f, score=%.6f\n", 0, 0.0, model.Score) start := time.Now() frame := 0 diff --git a/primitive/model.go b/primitive/model.go index 80f49ae..31fa6f5 100644 --- a/primitive/model.go +++ b/primitive/model.go @@ -22,7 +22,7 @@ type Model struct { Workers []*Worker } -func NewModel(target image.Image, background Color, size, numWorkers int) *Model { +func NewModel(target image.Image, background Color, size, numWorkers int, seed int64) *Model { w := target.Bounds().Size().X h := target.Bounds().Size().Y aspect := float64(w) / float64(h) @@ -48,7 +48,7 @@ func NewModel(target image.Image, background Color, size, numWorkers int) *Model model.Score = differenceFull(model.Target, model.Current) model.Context = model.newContext() for i := 0; i < numWorkers; i++ { - worker := NewWorker(model.Target) + worker := NewWorker(model.Target, seed) model.Workers = append(model.Workers, worker) } return model diff --git a/primitive/worker.go b/primitive/worker.go index d99eed5..58c2d30 100644 --- a/primitive/worker.go +++ b/primitive/worker.go @@ -3,7 +3,6 @@ package primitive import ( "image" "math/rand" - "time" "github.com/golang/freetype/raster" ) @@ -21,7 +20,7 @@ type Worker struct { Counter int } -func NewWorker(target *image.RGBA) *Worker { +func NewWorker(target *image.RGBA, seed int64) *Worker { w := target.Bounds().Size().X h := target.Bounds().Size().Y worker := Worker{} @@ -32,7 +31,7 @@ func NewWorker(target *image.RGBA) *Worker { worker.Rasterizer = raster.NewRasterizer(w, h) worker.Lines = make([]Scanline, 0, 4096) // TODO: based on height worker.Heatmap = NewHeatmap(w, h) - worker.Rnd = rand.New(rand.NewSource(time.Now().UnixNano())) + worker.Rnd = rand.New(rand.NewSource(seed)) return &worker }