github.com/randomizedcoder/goTrackRTP@v0.0.2/trackRTP_math.go (about) 1 package goTrackRTP 2 3 // https://github.com/randomizedcoder/goTracker/ 4 5 // Math related functions ( sequence wrap handling ) 6 7 // Quote: 8 // This function works by comparing the two numbers and their difference. 9 // If their difference is less than 1/2 the maximum sequence number value, 10 // then they must be close together - so we just check if one is greater 11 // than the other, as usual. 12 // However, if they are far apart, their difference will be greater than 1/2 13 // the max sequence, then we paradoxically consider the sequence number more 14 // recent if it is less than the current sequence number. 15 // https://gafferongames.com/post/reliability_ordering_and_congestion_avoidance_over_udp/ 16 17 // See also: https://dave.cheney.net/2013/06/30/how-to-write-benchmarks-in-go 18 19 // Using Less because the btree library uses less 20 // https://github.com/google/btree/blob/v1.1.2/btree_generic.go#L135 21 22 // isLess(seq, m uint16) is !isGreater 23 // NOTE seq is first argument!! We swap them here 24 func isLess[T uint16](s1, s2 uint16) bool { 25 //log.Printf("isLess, s1:%d, s2:%d", s1, s2) 26 b := isLessBranchless(s1, s2) 27 //log.Printf("isLess, isLessBranchless(seq, m):%t", b) 28 return b 29 } 30 31 // isLessBranchless is a non-banching (if-ess) version to find less that handles sequence wrapping 32 func isLessBranchless(s1, s2 uint16) bool { 33 34 diff := int(s1) - int(s2) 35 36 diff += int(maxUint16/2) + 1 37 diff &= int(maxUint16) 38 39 return diff > 0 && diff <= int(maxUint16/2) 40 } 41 42 // isLessBranch is a banching (if) version to find less that handles sequence wrapping 43 func isLessBranch(s1, s2 uint16) bool { 44 45 if s1 < s2 { 46 return s2-s1 <= maxUint16/2 47 } else { 48 return s1-s2 > maxUint16/2 49 } 50 } 51 52 // uint16Diff returns difference in uint16 sequence handling wrapping 53 func uint16Diff(s1, s2 uint16) uint16 { 54 55 //log.Printf("uint16Diff, m:%d, seq:%d", m, seq) 56 57 if s1 == s2 { 58 return 0 59 } 60 61 var abs uint16 62 if s1 < s2 { 63 abs = s2 - s1 64 } else { 65 abs = s1 - s2 66 } 67 68 if abs > maxUint16/2 { 69 return maxUint16 - abs + 1 70 } 71 72 //log.Printf("uint16Diff, s1:%d, s2:%d, abs:%d", s1, s2, abs) 73 74 return abs 75 } 76 77 // // isGreater determines if seq is ahead of m 78 // func isGreater[T uint16](m, seq uint16) bool { 79 // return isGreaterBranchless(m, seq) 80 // } 81 // // isGreaterBranchless determines if seq is ahead of m 82 // // branchless version 83 // func isGreaterBranchless[T uint16](m, seq uint16) bool { 84 85 // diff := int(m) - int(seq) 86 // diff += int(maxUint16/2) + 1 87 // diff &= int(maxUint16) 88 89 // return diff > 0 && diff <= int(maxUint16/2) 90 // } 91 92 // // isGreater determines if seq is ahead of m 93 // func isGreaterBranch[T uint16](m, seq uint16) bool { 94 // if m < seq { 95 // return seq-m <= maxUint16/2 96 // } else { 97 // return m-seq > maxUint16/2 98 // } 99 // }