@@ -20,6 +20,7 @@ import kotlin.jvm.JvmField
2020import kotlin.jvm.JvmName
2121import kotlin.jvm.JvmOverloads
2222import kotlin.jvm.JvmStatic
23+ import kotlin.math.min
2324
2425/* *
2526 * An immutable sequence of bytes.
@@ -137,6 +138,98 @@ internal constructor(data: ByteArray) : Comparable<ByteString> {
137138
138139 override fun compareTo (other : ByteString ): Int
139140
141+ /* *
142+ * Projects this value to the range `[0..size)` using linear interpolation. This is equivalent to
143+ * a sorted partitioning of all possible byte strings across [size] equally-sized buckets and
144+ * returning the index of the bucket that this byte string fits in.
145+ *
146+ * For example, the byte string `8000` is the median of all 2-element byte strings, and calling
147+ * `toIndex(100)` on it returns 50. Some other examples:
148+ *
149+ * | Byte String (hex) | `toIndex(100)` | `toIndex(256)` | `toIndex(Int.MAX_VALUE)` |
150+ * | :----------------- | -------------: | -------------: | -----------------------: |
151+ * | (empty) | 0 | 0 | 0 |
152+ * | 00 | 0 | 0 | 0 |
153+ * | 0000 | 0 | 0 | 0 |
154+ * | 000000 | 0 | 0 | 0 |
155+ * | 0000000001 | 0 | 0 | 0 |
156+ * | 00000001 | 0 | 0 | 0 |
157+ * | 00000002 | 0 | 0 | 0 |
158+ * | 00000003 | 0 | 0 | 1 |
159+ * | 01 | 0 | 1 | 8388607 |
160+ * | 02 | 0 | 2 | 16777215 |
161+ * | 03 | 1 | 3 | 25165823 |
162+ * | 80 | 50 | 128 | 1073741823 |
163+ * | 8000 | 50 | 128 | 1073741823 |
164+ * | 80000000 | 50 | 128 | 1073741823 |
165+ * | 81 | 50 | 129 | 1082130431 |
166+ * | 81ffffff | 50 | 129 | 1090519038 |
167+ * | 82 | 50 | 130 | 1090519039 |
168+ * | 83 | 51 | 131 | 1098907647 |
169+ * | ff | 99 | 255 | 2139095039 |
170+ * | ffff | 99 | 255 | 2147450879 |
171+ * | ffffffff | 99 | 255 | 2147483646 |
172+ * | ffffffffffff | 99 | 255 | 2147483646 |
173+ *
174+ * This interprets the bytes in this byte string as **unsigned**. This behavior is consistent with
175+ * [compareTo]. The returned value is also consistent with [compareTo] though the dynamic range
176+ * is compressed. For two byte strings `a` and `b`, if `a < b`, then
177+ * `a.toIndex(n) <= b.toIndex(n)` for all sizes `n`.
178+ *
179+ * This examines at most the first 4 bytes of this byte string. Data beyond the first 4 bytes is
180+ * not used to compute the result.
181+ *
182+ * @param size a positive integer.
183+ * @return a value that is greater than or equal to `0` and less than [size].
184+ */
185+ fun toIndex (size : Int ): Int
186+
187+ /* *
188+ * Projects this value to the range `[0.0..1.0)` using linear interpolation. This is equivalent to
189+ * sorting all possible byte strings and returning the fraction that precede this byte string.
190+ *
191+ * For example, the byte string `8000` is the median of all 2-element byte strings, and calling
192+ * `toFraction()` on it returns 0.5. Some other examples:
193+ *
194+ * | Byte String (hex) | `toFraction()` |
195+ * | :----------------- | :----------------- |
196+ * | (empty) | 0.0 |
197+ * | 00 | 0.0 |
198+ * | 0000 | 0.0 |
199+ * | 000000 | 0.0 |
200+ * | 00000000000001 | 0.0 |
201+ * | 00000000000007 | 0.0 |
202+ * | 00000000000008 | 0.0000000000000001 |
203+ * | 0000000001 | 0.0000000000009094 |
204+ * | 00000001 | 0.0000000002328306 |
205+ * | 01 | 0.00390625 |
206+ * | 02 | 0.0078125 |
207+ * | 03 | 0.01171875 |
208+ * | 80 | 0.5 |
209+ * | 8000 | 0.5 |
210+ * | 80000000000000 | 0.5 |
211+ * | 81 | 0.50390625 |
212+ * | 81ffffff | 0.5078124997671694 |
213+ * | 82 | 0.5078125 |
214+ * | 83 | 0.51171875 |
215+ * | ff | 0.99609375 |
216+ * | ffff | 0.9999847412109375 |
217+ * | ffffffff | 0.9999999997671694 |
218+ * | ffffffffffff | 0.9999999999999964 |
219+ * | ffffffffffffff | 0.9999999999999999 |
220+ *
221+ * This interprets the bytes in this byte string as **unsigned**. This behavior is consistent with
222+ * [compareTo]. The returned value is also consistent with [compareTo] though the dynamic range
223+ * is compressed. For two byte strings `a` and `b`, if `a < b`, then
224+ * `a.toFraction() <= b.toFraction()`.
225+ *
226+ * This examines at most the first 7 bytes of this byte string. Data beyond the first 7 bytes is
227+ * not used to compute the result.
228+ *
229+ * @return a value that is greater than or equal to `0.0` and less than `1.0`.
230+ */
231+ fun toFraction (): Double
232+
140233 /* *
141234 * Returns a human-readable string that describes the contents of this byte string. Typically this
142235 * is a string like `[text=Hello]` or `[hex=0000ffff]`.
0 commit comments