+
+/**
+ * Updates the given measurement statistics.
+ *
+ * @param measurementStatistics - The measurement statistics to update.
+ * @param measurementRequirements - The measurement statistics requirements.
+ * @param measurementValue - The measurement value.
+ * @param numberOfMeasurements - The number of measurements.
+ * @internal
+ */
+export const updateMeasurementStatistics = (
+ measurementStatistics: MeasurementStatistics,
+ measurementRequirements: MeasurementStatisticsRequirements,
+ measurementValue: number
+): void => {
+ if (measurementRequirements.aggregate) {
+ measurementStatistics.aggregate =
+ (measurementStatistics.aggregate ?? 0) + measurementValue
+ measurementStatistics.minimum = Math.min(
+ measurementValue,
+ measurementStatistics.minimum ?? Infinity
+ )
+ measurementStatistics.maximum = Math.max(
+ measurementValue,
+ measurementStatistics.maximum ?? -Infinity
+ )
+ if (
+ (measurementRequirements.average || measurementRequirements.median) &&
+ measurementValue != null
+ ) {
+ measurementStatistics.history.push(measurementValue)
+ if (measurementRequirements.average) {
+ measurementStatistics.average = average(measurementStatistics.history)
+ }
+ if (measurementRequirements.median) {
+ measurementStatistics.median = median(measurementStatistics.history)
+ }
+ }
+ }
+}
+
+/**
+ * Executes a function once at a time.
+ *
+ * @param fn - The function to execute.
+ * @param context - The context to bind the function to.
+ * @returns The function to execute.
+ */
+export const once = (
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ fn: (...args: any[]) => void,
+ context: unknown
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+): ((...args: any[]) => void) => {
+ let called = false
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ return function (...args: any[]): void {
+ if (!called) {
+ called = true
+ fn.apply(context, args)
+ called = false
+ }
+ }
+}
+
+/**
+ * Generate a cryptographically secure random number in the [0,1[ range
+ *
+ * @returns A number in the [0,1[ range
+ */
+export const secureRandom = (): number => {
+ return webcrypto.getRandomValues(new Uint32Array(1))[0] / 0x100000000
+}