github.com/weaviate/weaviate@v1.24.6/adapters/repos/db/vector/hnsw/distancer/manhattan.go (about)

     1  //                           _       _
     2  // __      _____  __ ___   ___  __ _| |_ ___
     3  // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
     4  //  \ V  V /  __/ (_| |\ V /| | (_| | ||  __/
     5  //   \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
     6  //
     7  //  Copyright © 2016 - 2024 Weaviate B.V. All rights reserved.
     8  //
     9  //  CONTACT: hello@weaviate.io
    10  //
    11  
    12  package distancer
    13  
    14  import (
    15  	"math"
    16  
    17  	"github.com/pkg/errors"
    18  )
    19  
    20  var manhattanImpl func(a, b []float32) float32 = func(a, b []float32) float32 {
    21  	var sum float32
    22  
    23  	for i := range a {
    24  		// take absolute difference, converted to float64 because math.Abs needs that
    25  		// convert back to float32 as sum is float32
    26  		sum += float32(math.Abs(float64(a[i] - b[i])))
    27  	}
    28  
    29  	return sum
    30  }
    31  
    32  type Manhattan struct {
    33  	a []float32
    34  }
    35  
    36  func (l Manhattan) Distance(b []float32) (float32, bool, error) {
    37  	if len(l.a) != len(b) {
    38  		return 0, false, errors.Errorf("vector lengths don't match: %d vs %d",
    39  			len(l.a), len(b))
    40  	}
    41  
    42  	return manhattanImpl(l.a, b), true, nil
    43  }
    44  
    45  type ManhattanProvider struct{}
    46  
    47  func NewManhattanProvider() ManhattanProvider {
    48  	return ManhattanProvider{}
    49  }
    50  
    51  func (l ManhattanProvider) SingleDist(a, b []float32) (float32, bool, error) {
    52  	if len(a) != len(b) {
    53  		return 0, false, errors.Errorf("vector lengths don't match: %d vs %d",
    54  			len(a), len(b))
    55  	}
    56  
    57  	return manhattanImpl(a, b), true, nil
    58  }
    59  
    60  func (l ManhattanProvider) Type() string {
    61  	return "manhattan"
    62  }
    63  
    64  func (l ManhattanProvider) New(a []float32) Distancer {
    65  	return &Manhattan{a: a}
    66  }
    67  
    68  func (l ManhattanProvider) Step(x, y []float32) float32 {
    69  	var sum float32
    70  
    71  	for i := range x {
    72  		// take absolute difference, converted to float64 because math.Abs needs that
    73  		// convert back to float32 as sum is float32
    74  		sum += float32(math.Abs(float64(x[i] - y[i])))
    75  	}
    76  
    77  	return sum
    78  }
    79  
    80  func (l ManhattanProvider) Wrap(x float32) float32 {
    81  	return x
    82  }