github.com/thiagoyeds/go-cloud@v0.26.0/docstore/driver/compare.go (about) 1 // Copyright 2019 The Go Cloud Development Kit Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Useful comparison functions. 16 17 package driver 18 19 import ( 20 "fmt" 21 "math/big" 22 "reflect" 23 "time" 24 ) 25 26 // CompareTimes returns -1, 1 or 0 depending on whether t1 is before, after or 27 // equal to t2. 28 func CompareTimes(t1, t2 time.Time) int { 29 switch { 30 case t1.Before(t2): 31 return -1 32 case t1.After(t2): 33 return 1 34 default: 35 return 0 36 } 37 } 38 39 // CompareNumbers returns -1, 1 or 0 depending on whether n1 is less than, 40 // greater than or equal to n2. n1 and n2 must be signed integer, unsigned 41 // integer, or floating-point values, but they need not be the same type. 42 // 43 // If both types are integers or both floating-point, CompareNumbers behaves 44 // like Go comparisons on those types. If one operand is integer and the other 45 // is floating-point, CompareNumbers correctly compares the mathematical values 46 // of the numbers, without loss of precision. 47 func CompareNumbers(n1, n2 interface{}) (int, error) { 48 v1, ok := n1.(reflect.Value) 49 if !ok { 50 v1 = reflect.ValueOf(n1) 51 } 52 v2, ok := n2.(reflect.Value) 53 if !ok { 54 v2 = reflect.ValueOf(n2) 55 } 56 f1, err := toBigFloat(v1) 57 if err != nil { 58 return 0, err 59 } 60 f2, err := toBigFloat(v2) 61 if err != nil { 62 return 0, err 63 } 64 return f1.Cmp(f2), nil 65 } 66 67 func toBigFloat(x reflect.Value) (*big.Float, error) { 68 var f big.Float 69 switch x.Kind() { 70 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 71 f.SetInt64(x.Int()) 72 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 73 f.SetUint64(x.Uint()) 74 case reflect.Float32, reflect.Float64: 75 f.SetFloat64(x.Float()) 76 default: 77 typ := "nil" 78 if x.IsValid() { 79 typ = fmt.Sprint(x.Type()) 80 } 81 return nil, fmt.Errorf("%v of type %s is not a number", x, typ) 82 } 83 return &f, nil 84 }