commit 698e838b97a90c678224912b29b5920c1b0e030a Author: sashakoshka@tebibyte.media Date: Sun Jun 23 08:45:58 2024 -0400 Initial commit diff --git a/container/memo.go b/container/memo.go new file mode 100644 index 0000000..351821b --- /dev/null +++ b/container/memo.go @@ -0,0 +1,39 @@ +package ucontainer + +// Memo holds a cached value. +type Memo[T any] struct { + cache T + valid bool + update func () T +} + +// NewMemo creates a new Memo which will take its value from the specified +// update callback. +func NewMemo[T any] (update func () T) Memo[T] { + return Memo[T] { + update: update, + } +} + +// Value returns the Memo's value, updating it if the current cached value is +// invalid. +func (this *Memo[T]) Value () T { + if !this.valid { + this.cache = this.update() + } + return this.cache +} + +// Invalidate marks the Memo's value as invalid, which will cause it to be +// updated the next time Value is called. +func (this *Memo[T]) Invalidate () { + this.valid = false +} + +// InvalidateTo invalidates the Memo and sets its value. The new value will be +// entirely inaccessible. This is only intended to be used for setting a +// reference to nil +func (this *Memo[T]) InvalidateTo (value T) { + this.Invalidate() + this.cache = value +} diff --git a/container/set.go b/container/set.go new file mode 100644 index 0000000..e26fd07 --- /dev/null +++ b/container/set.go @@ -0,0 +1,33 @@ +package ucontainer + +// Set is a set of unique items, built on top of map. +type Set[T comparable] map[T] struct { } + +// Empty returns true if there are no items in the set. +func (set Set[T]) Empty () bool { + return set == nil || len(set) == 0 +} + +// Has returns true if the set contains item. +func (set Set[T]) Has (item T) bool { + if set == nil { + return false + } + _, ok := set[item] + return ok +} + +// Add adds an item to the set. +func (set Set[T]) Add (item T) { + set[item] = struct { } { } +} + +// Pop removes the first accessible item from the set and returns it. +func (set Set[T]) Pop () (item T) { + for item := range set { + delete(set, item) + return item + } + return +} + diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..4466c4e --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.tebibyte.media/sashakoshka/goutil + +go 1.22.4 diff --git a/image/color/color.go b/image/color/color.go new file mode 100644 index 0000000..b24632b --- /dev/null +++ b/image/color/color.go @@ -0,0 +1,9 @@ +package ucolor + +import "image/color" + +// Transparent returns whether or not a color has transparency. +func Transparent (c color.Color) bool { + _, _, _, a := c.RGBA() + return a != 0xFFFF +} diff --git a/image/path/path.go b/image/path/path.go new file mode 100644 index 0000000..4ed1abf --- /dev/null +++ b/image/path/path.go @@ -0,0 +1,38 @@ +package upath + +import "math" +import "image" + +// P creates a path fom a list of integers that form X-Y pairs. +func P (data ...int) []image.Point { + result := make([]image.Point, len(data) / 2) + for index := range result { + result[index].X = data[index * 2] + result[index].Y = data[index * 2 + 1] + } + return result +} + +// Lerp linearally interpolates between two paths. If the paths differ in +// length, the returned path will only be as long as the smaller one. +func Lerp (fac float64, start, end []image.Point) []image.Point { + result := make([]image.Point, len(start)) + for index, startPt := range start { + if index >= len(end) { return result[:index] } + endPt := end[index] + result[index] = image.Pt ( + lerp(fac, startPt.X, endPt.X), + lerp(fac, startPt.Y, endPt.Y)) + } + return result +} + +// Distance returns the distance between two points. +func Distance (start, end image.Point) float64 { + delta := start.Sub(end) + return math.Sqrt(float64(delta.X * delta.X) + float64(delta.Y * delta.Y)) +} + +func lerp (fac float64, x, y int) int { + return int(float64(x) * fac + float64(y) * (1.0 - fac)) +}