Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
arjunsk committed Feb 15, 2024
1 parent 2d63086 commit d79f2b5
Show file tree
Hide file tree
Showing 50 changed files with 3,406 additions and 2,343 deletions.
66 changes: 66 additions & 0 deletions assertx/float64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright 2023 Matrix Origin
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package assertx

import (
"math"
)

// Float64 values have minor numerical differences between Apple M2 and Linux EC2,
// so we use an epsilon value to compare them in UT. We could not use reflect.DeepEqual because
// of these minor differences. We cannot use assert.InEpsilon because it requires the first
// argument to be non-zero.
//
// The epsilon 1e-9 epsilon is based on the following observation:
// - `strconv.FormatFloat(float64(value), 'f', -1, 64)` we use for outputting float64 values.
// - precision difference between Apple M2 and Linux EC2 float64 results (approx 1e-13)
// - service_weaver: https://github.com/ServiceWeaver/weaver/blob/8e7c225542b8f8267ec0da3e01a098366b6f8daf/internal/weaver/load.go#L31
// - google lib: https://github.com/google/differential-privacy/blob/91b4ecebf33e71b8a215b7ea8325fb5e47b12671/privacy-on-beam/pbeam/pbeamtest/pbeamtest_test.go#L1406
const float64EqualityThreshold = 1e-9

// InEpsilonF64Slices returns true if all the elements in v1 and v2 are within epsilon of each other.
func InEpsilonF64Slices(want, got [][]float64) bool {
if len(want) != len(got) {
return false
}

for i := 0; i < len(want); i++ {
if !InEpsilonF64Slice(want[i], got[i]) {
return false
}
}
return true
}

// InEpsilonF64Slice returns true if all the elements in v1 and v2 are within epsilon of each other.
// assert.InEpsilonSlice requires v1 to be non-zero.
func InEpsilonF64Slice(want, got []float64) bool {
if len(want) != len(got) {
return false
}

for i := 0; i < len(want); i++ {
if !InEpsilonF64(want[i], got[i]) {
return false
}
}
return true
}

// InEpsilonF64 returns true if v1 and v2 are within epsilon of each other.
// assert.InEpsilon requires v1 to be non-zero.
func InEpsilonF64(want, got float64) bool {
return want == got || math.Abs(want-got) < float64EqualityThreshold || (math.IsNaN(want) && math.IsNaN(got))
}
166 changes: 166 additions & 0 deletions assertx/float64_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// Copyright 2023 Matrix Origin
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package assertx

import "testing"

func TestInEpsilonF64(t *testing.T) {
type args struct {
want float64
got float64
}
tests := []struct {
name string
args args
want bool
}{

{
name: "Test 1 - difference is epsilon",
args: args{
want: 2.0,
got: 2.0 + float64EqualityThreshold,
},
want: false,
},
{
name: "Test 2.a - difference is less than epsilon",
args: args{
want: 2.0,
got: 2.0 + 0.5*float64EqualityThreshold,
},
want: true,
},
{
name: "Test 2.b - difference is more than epsilon",
args: args{
want: 2.0,
got: 2.0 + 2*float64EqualityThreshold,
},
want: false,
},
{
name: "Test 2.c - difference is -ve of epsilon",
args: args{
want: 2.0,
got: 2.0 - float64EqualityThreshold,
},
want: false,
},
{
name: "Test 3 - till 9th digit is same, 10th digit is different",
args: args{
want: 1.732050800_0,
got: 1.732050800_9,
},
want: true,
},
{
name: "Test 4 - 9th digit is different",
args: args{
want: 1.73205080_0,
got: 1.73205080_9,
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := InEpsilonF64(tt.args.want, tt.args.got); got != tt.want {
t.Errorf("%s InEpsilonF64() = %v, want %v", tt.name, got, tt.want)
}
})
}
}

func TestInEpsilonF64Slice(t *testing.T) {
type args struct {
want []float64
got []float64
}
tests := []struct {
name string
args args
want bool
}{
{
name: "Test 1 - difference is epsilon",
args: args{
want: []float64{2.0, 3.0},
got: []float64{2.0 + float64EqualityThreshold, 3.0 + float64EqualityThreshold},
},
want: false,
},
{
name: "Test 2 - till 9th digit is same, 10th digit is different)",
args: args{
want: []float64{1.732050800_0},
got: []float64{1.732050800_9},
},
want: true,
},
{
name: "Test 3 - 9th digit is different",
args: args{
want: []float64{1.73205080_0},
got: []float64{1.73205080_9},
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := InEpsilonF64Slice(tt.args.want, tt.args.got); got != tt.want {
t.Errorf("InEpsilonF64Slice() = %v, want %v", got, tt.want)
}
})
}
}

func TestInEpsilonF64Slices(t *testing.T) {
type args struct {
want [][]float64
got [][]float64
}
tests := []struct {
name string
args args
want bool
}{
{
name: "Test 1 - difference is epsilon",
args: args{
want: [][]float64{{2.0, 3.0}, {4.0}},
got: [][]float64{{2.0 + float64EqualityThreshold, 3.0 + float64EqualityThreshold}, {4.0}},
},
want: false,
},
{
name: "Test 2 - difference is less than epsilon (next neg-power of epsilon & epsilon/2)",
args: args{
want: [][]float64{{2.0, 3.0}, {4.0}},
got: [][]float64{{2.0 + 1e-1*float64EqualityThreshold, 3.0 + float64EqualityThreshold/2}, {4.0}},
},
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := InEpsilonF64Slices(tt.args.want, tt.args.got); got != tt.want {
t.Errorf("InEpsilonF64Slices() = %v, want %v", got, tt.want)
}
})
}
}
81 changes: 0 additions & 81 deletions clusterer/clusterer_bench_test.go

This file was deleted.

57 changes: 0 additions & 57 deletions clusterer/clusterer_test.go

This file was deleted.

8 changes: 0 additions & 8 deletions clusterer/docs.go

This file was deleted.

Loading

0 comments on commit d79f2b5

Please sign in to comment.