@gzl10/ts-helpers 4.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/CHANGELOG.md +320 -0
  2. package/README.md +233 -0
  3. package/USAGE-GUIDE.md +800 -0
  4. package/dist/browser/async.js +15 -0
  5. package/dist/browser/async.js.map +1 -0
  6. package/dist/browser/chunk-4O7ZPIJN.js +383 -0
  7. package/dist/browser/chunk-4O7ZPIJN.js.map +1 -0
  8. package/dist/browser/chunk-75XNTC34.js +60 -0
  9. package/dist/browser/chunk-75XNTC34.js.map +1 -0
  10. package/dist/browser/chunk-C3D7YZVE.js +299 -0
  11. package/dist/browser/chunk-C3D7YZVE.js.map +1 -0
  12. package/dist/browser/chunk-CZL6C2EI.js +452 -0
  13. package/dist/browser/chunk-CZL6C2EI.js.map +1 -0
  14. package/dist/browser/chunk-D4FZFIVA.js +240 -0
  15. package/dist/browser/chunk-D4FZFIVA.js.map +1 -0
  16. package/dist/browser/chunk-IL7NG7IC.js +72 -0
  17. package/dist/browser/chunk-IL7NG7IC.js.map +1 -0
  18. package/dist/browser/chunk-NSBPE2FW.js +17 -0
  19. package/dist/browser/chunk-NSBPE2FW.js.map +1 -0
  20. package/dist/browser/chunk-SLQVNPTH.js +27 -0
  21. package/dist/browser/chunk-SLQVNPTH.js.map +1 -0
  22. package/dist/browser/chunk-WG7ILCUB.js +195 -0
  23. package/dist/browser/chunk-WG7ILCUB.js.map +1 -0
  24. package/dist/browser/chunk-WJA4JDMZ.js +278 -0
  25. package/dist/browser/chunk-WJA4JDMZ.js.map +1 -0
  26. package/dist/browser/chunk-ZFVYLUTT.js +65 -0
  27. package/dist/browser/chunk-ZFVYLUTT.js.map +1 -0
  28. package/dist/browser/chunk-ZYTSVMTI.js +263 -0
  29. package/dist/browser/chunk-ZYTSVMTI.js.map +1 -0
  30. package/dist/browser/dates.js +78 -0
  31. package/dist/browser/dates.js.map +1 -0
  32. package/dist/browser/environment-detection.js +21 -0
  33. package/dist/browser/environment-detection.js.map +1 -0
  34. package/dist/browser/environment.js +34 -0
  35. package/dist/browser/environment.js.map +1 -0
  36. package/dist/browser/errors.js +18 -0
  37. package/dist/browser/errors.js.map +1 -0
  38. package/dist/browser/index.js +412 -0
  39. package/dist/browser/index.js.map +1 -0
  40. package/dist/browser/math.js +51 -0
  41. package/dist/browser/math.js.map +1 -0
  42. package/dist/browser/number.js +10 -0
  43. package/dist/browser/number.js.map +1 -0
  44. package/dist/browser/objects.js +31 -0
  45. package/dist/browser/objects.js.map +1 -0
  46. package/dist/browser/strings.js +80 -0
  47. package/dist/browser/strings.js.map +1 -0
  48. package/dist/browser/validation-core.js +54 -0
  49. package/dist/browser/validation-core.js.map +1 -0
  50. package/dist/browser/validation-crypto.js +28 -0
  51. package/dist/browser/validation-crypto.js.map +1 -0
  52. package/dist/browser/validators.js +98 -0
  53. package/dist/browser/validators.js.map +1 -0
  54. package/dist/cjs/async.js +86 -0
  55. package/dist/cjs/async.js.map +1 -0
  56. package/dist/cjs/dates.js +285 -0
  57. package/dist/cjs/dates.js.map +1 -0
  58. package/dist/cjs/environment-detection.js +84 -0
  59. package/dist/cjs/environment-detection.js.map +1 -0
  60. package/dist/cjs/environment.js +261 -0
  61. package/dist/cjs/environment.js.map +1 -0
  62. package/dist/cjs/errors.js +80 -0
  63. package/dist/cjs/errors.js.map +1 -0
  64. package/dist/cjs/index.js +2035 -0
  65. package/dist/cjs/index.js.map +1 -0
  66. package/dist/cjs/math.js +388 -0
  67. package/dist/cjs/math.js.map +1 -0
  68. package/dist/cjs/number.js +37 -0
  69. package/dist/cjs/number.js.map +1 -0
  70. package/dist/cjs/objects.js +249 -0
  71. package/dist/cjs/objects.js.map +1 -0
  72. package/dist/cjs/strings.js +253 -0
  73. package/dist/cjs/strings.js.map +1 -0
  74. package/dist/cjs/validation.js +450 -0
  75. package/dist/cjs/validation.js.map +1 -0
  76. package/dist/esm/async.js +15 -0
  77. package/dist/esm/async.js.map +1 -0
  78. package/dist/esm/chunk-4O7ZPIJN.js +383 -0
  79. package/dist/esm/chunk-4O7ZPIJN.js.map +1 -0
  80. package/dist/esm/chunk-75XNTC34.js +60 -0
  81. package/dist/esm/chunk-75XNTC34.js.map +1 -0
  82. package/dist/esm/chunk-BDOBKBKA.js +72 -0
  83. package/dist/esm/chunk-BDOBKBKA.js.map +1 -0
  84. package/dist/esm/chunk-C3D7YZVE.js +299 -0
  85. package/dist/esm/chunk-C3D7YZVE.js.map +1 -0
  86. package/dist/esm/chunk-CZL6C2EI.js +452 -0
  87. package/dist/esm/chunk-CZL6C2EI.js.map +1 -0
  88. package/dist/esm/chunk-EBLSTOEC.js +263 -0
  89. package/dist/esm/chunk-EBLSTOEC.js.map +1 -0
  90. package/dist/esm/chunk-NSBPE2FW.js +17 -0
  91. package/dist/esm/chunk-NSBPE2FW.js.map +1 -0
  92. package/dist/esm/chunk-SLQVNPTH.js +27 -0
  93. package/dist/esm/chunk-SLQVNPTH.js.map +1 -0
  94. package/dist/esm/chunk-WG7ILCUB.js +195 -0
  95. package/dist/esm/chunk-WG7ILCUB.js.map +1 -0
  96. package/dist/esm/chunk-WJA4JDMZ.js +278 -0
  97. package/dist/esm/chunk-WJA4JDMZ.js.map +1 -0
  98. package/dist/esm/chunk-ZFVYLUTT.js +65 -0
  99. package/dist/esm/chunk-ZFVYLUTT.js.map +1 -0
  100. package/dist/esm/dates.js +78 -0
  101. package/dist/esm/dates.js.map +1 -0
  102. package/dist/esm/environment-detection.js +21 -0
  103. package/dist/esm/environment-detection.js.map +1 -0
  104. package/dist/esm/environment.js +34 -0
  105. package/dist/esm/environment.js.map +1 -0
  106. package/dist/esm/errors.js +18 -0
  107. package/dist/esm/errors.js.map +1 -0
  108. package/dist/esm/index.js +380 -0
  109. package/dist/esm/index.js.map +1 -0
  110. package/dist/esm/math.js +51 -0
  111. package/dist/esm/math.js.map +1 -0
  112. package/dist/esm/number.js +10 -0
  113. package/dist/esm/number.js.map +1 -0
  114. package/dist/esm/objects.js +31 -0
  115. package/dist/esm/objects.js.map +1 -0
  116. package/dist/esm/strings.js +80 -0
  117. package/dist/esm/strings.js.map +1 -0
  118. package/dist/esm/validation.js +54 -0
  119. package/dist/esm/validation.js.map +1 -0
  120. package/dist/node/async.js +93 -0
  121. package/dist/node/async.js.map +1 -0
  122. package/dist/node/csv.js +102 -0
  123. package/dist/node/csv.js.map +1 -0
  124. package/dist/node/data.js +880 -0
  125. package/dist/node/data.js.map +1 -0
  126. package/dist/node/dates.js +324 -0
  127. package/dist/node/dates.js.map +1 -0
  128. package/dist/node/environment.js +278 -0
  129. package/dist/node/environment.js.map +1 -0
  130. package/dist/node/errors.js +89 -0
  131. package/dist/node/errors.js.map +1 -0
  132. package/dist/node/index.js +3151 -0
  133. package/dist/node/index.js.map +1 -0
  134. package/dist/node/json.js +107 -0
  135. package/dist/node/json.js.map +1 -0
  136. package/dist/node/math.js +413 -0
  137. package/dist/node/math.js.map +1 -0
  138. package/dist/node/number.js +42 -0
  139. package/dist/node/number.js.map +1 -0
  140. package/dist/node/objects.js +264 -0
  141. package/dist/node/objects.js.map +1 -0
  142. package/dist/node/strings.js +293 -0
  143. package/dist/node/strings.js.map +1 -0
  144. package/dist/node/tree.js +89 -0
  145. package/dist/node/tree.js.map +1 -0
  146. package/dist/node/validation-core.js +477 -0
  147. package/dist/node/validation-core.js.map +1 -0
  148. package/dist/node/validation-crypto.js +179 -0
  149. package/dist/node/validation-crypto.js.map +1 -0
  150. package/dist/node/validation.js +677 -0
  151. package/dist/node/validation.js.map +1 -0
  152. package/dist/node/validators.js +123 -0
  153. package/dist/node/validators.js.map +1 -0
  154. package/dist/node-esm/async.js +15 -0
  155. package/dist/node-esm/async.js.map +1 -0
  156. package/dist/node-esm/chunk-3YOF7NPT.js +299 -0
  157. package/dist/node-esm/chunk-3YOF7NPT.js.map +1 -0
  158. package/dist/node-esm/chunk-64TBXJQS.js +263 -0
  159. package/dist/node-esm/chunk-64TBXJQS.js.map +1 -0
  160. package/dist/node-esm/chunk-75XNTC34.js +60 -0
  161. package/dist/node-esm/chunk-75XNTC34.js.map +1 -0
  162. package/dist/node-esm/chunk-C4PKXIPB.js +278 -0
  163. package/dist/node-esm/chunk-C4PKXIPB.js.map +1 -0
  164. package/dist/node-esm/chunk-CMDFZME3.js +452 -0
  165. package/dist/node-esm/chunk-CMDFZME3.js.map +1 -0
  166. package/dist/node-esm/chunk-DZZPUYMP.js +74 -0
  167. package/dist/node-esm/chunk-DZZPUYMP.js.map +1 -0
  168. package/dist/node-esm/chunk-HTSEHRHI.js +195 -0
  169. package/dist/node-esm/chunk-HTSEHRHI.js.map +1 -0
  170. package/dist/node-esm/chunk-JCAUVOPH.js +27 -0
  171. package/dist/node-esm/chunk-JCAUVOPH.js.map +1 -0
  172. package/dist/node-esm/chunk-KBHE3K2F.js +505 -0
  173. package/dist/node-esm/chunk-KBHE3K2F.js.map +1 -0
  174. package/dist/node-esm/chunk-LYTET5NX.js +65 -0
  175. package/dist/node-esm/chunk-LYTET5NX.js.map +1 -0
  176. package/dist/node-esm/chunk-PZ5AY32C.js +10 -0
  177. package/dist/node-esm/chunk-PZ5AY32C.js.map +1 -0
  178. package/dist/node-esm/chunk-UKGXL2QO.js +383 -0
  179. package/dist/node-esm/chunk-UKGXL2QO.js.map +1 -0
  180. package/dist/node-esm/chunk-XAEYT23H.js +164 -0
  181. package/dist/node-esm/chunk-XAEYT23H.js.map +1 -0
  182. package/dist/node-esm/csv.js +63 -0
  183. package/dist/node-esm/csv.js.map +1 -0
  184. package/dist/node-esm/data.js +32 -0
  185. package/dist/node-esm/data.js.map +1 -0
  186. package/dist/node-esm/dates.js +78 -0
  187. package/dist/node-esm/dates.js.map +1 -0
  188. package/dist/node-esm/environment.js +34 -0
  189. package/dist/node-esm/environment.js.map +1 -0
  190. package/dist/node-esm/errors.js +18 -0
  191. package/dist/node-esm/errors.js.map +1 -0
  192. package/dist/node-esm/index.js +426 -0
  193. package/dist/node-esm/index.js.map +1 -0
  194. package/dist/node-esm/json.js +68 -0
  195. package/dist/node-esm/json.js.map +1 -0
  196. package/dist/node-esm/math.js +51 -0
  197. package/dist/node-esm/math.js.map +1 -0
  198. package/dist/node-esm/number.js +10 -0
  199. package/dist/node-esm/number.js.map +1 -0
  200. package/dist/node-esm/objects.js +31 -0
  201. package/dist/node-esm/objects.js.map +1 -0
  202. package/dist/node-esm/strings.js +80 -0
  203. package/dist/node-esm/strings.js.map +1 -0
  204. package/dist/node-esm/tree.js +8 -0
  205. package/dist/node-esm/tree.js.map +1 -0
  206. package/dist/node-esm/validation-core.js +54 -0
  207. package/dist/node-esm/validation-core.js.map +1 -0
  208. package/dist/node-esm/validation-crypto.js +26 -0
  209. package/dist/node-esm/validation-crypto.js.map +1 -0
  210. package/dist/node-esm/validation.js +606 -0
  211. package/dist/node-esm/validation.js.map +1 -0
  212. package/dist/node-esm/validators.js +98 -0
  213. package/dist/node-esm/validators.js.map +1 -0
  214. package/dist/types/async-C8gvbSG-.d.ts +453 -0
  215. package/dist/types/async.d.ts +1 -0
  216. package/dist/types/csv.d.ts +226 -0
  217. package/dist/types/data.d.ts +1561 -0
  218. package/dist/types/dates-hTiE0Z11.d.ts +298 -0
  219. package/dist/types/dates.d.ts +1 -0
  220. package/dist/types/environment-B8eLS7KT.d.ts +420 -0
  221. package/dist/types/environment-detection.d.ts +102 -0
  222. package/dist/types/environment.d.ts +1 -0
  223. package/dist/types/errors.d.ts +147 -0
  224. package/dist/types/index.d.ts +211 -0
  225. package/dist/types/json.d.ts +284 -0
  226. package/dist/types/math-BQ9Lwdp7.d.ts +2060 -0
  227. package/dist/types/math.d.ts +1 -0
  228. package/dist/types/number-CYnQfLWj.d.ts +44 -0
  229. package/dist/types/number.d.ts +1 -0
  230. package/dist/types/objects-BohS8GCS.d.ts +1185 -0
  231. package/dist/types/objects.d.ts +1 -0
  232. package/dist/types/strings-CiqRPYLL.d.ts +1349 -0
  233. package/dist/types/strings.d.ts +1 -0
  234. package/dist/types/tree.d.ts +284 -0
  235. package/dist/types/validation-core-DfHF8rCG.d.ts +238 -0
  236. package/dist/types/validation-crypto-browser.d.ts +56 -0
  237. package/dist/types/validation-crypto-node.d.ts +31 -0
  238. package/dist/types/validation.d.ts +1 -0
  239. package/dist/types/validators.d.ts +216 -0
  240. package/package.json +253 -0
@@ -0,0 +1,2060 @@
1
+ /**
2
+ * Mathematical calculations, statistics, and financial utilities
3
+ * Consolidated from specialized/math module
4
+ */
5
+ /**
6
+ * Mathematical operations configuration for data aggregation
7
+ * @template T - The type of objects being processed
8
+ * @example
9
+ * ```ts
10
+ * // Simple operations configuration
11
+ * const ops: IMathOp = {
12
+ * $sum: ['amount', 'quantity'],
13
+ * $avg: ['price', 'rating'],
14
+ * $count: ['name'],
15
+ * $max: ['sales'],
16
+ * $min: ['cost']
17
+ * }
18
+ *
19
+ * // For sales data
20
+ * const salesOps: IMathOp<SalesRecord> = {
21
+ * $sum: ['revenue', 'units'],
22
+ * $avg: ['unitPrice'],
23
+ * $countUniq: ['customerId']
24
+ * }
25
+ * ```
26
+ */
27
+ interface IMathOp<T = any> {
28
+ /** Calculate average of numeric fields */
29
+ $avg?: (keyof T extends infer K ? K extends keyof T ? T[K] extends number ? K : never : never : never)[];
30
+ /** Count occurrences of string fields */
31
+ $count?: (keyof T extends infer K ? K extends keyof T ? T[K] extends string ? K : never : never : never)[];
32
+ /** Count unique values in fields */
33
+ $countUniq?: (keyof T)[];
34
+ /** Check if field exists (1/0) */
35
+ $exist?: (keyof T)[];
36
+ /** Find maximum value in numeric fields */
37
+ $max?: (keyof T extends infer K ? K extends keyof T ? T[K] extends number ? K : never : never : never)[];
38
+ /** Find minimum value in numeric fields */
39
+ $min?: (keyof T extends infer K ? K extends keyof T ? T[K] extends number ? K : never : never : never)[];
40
+ /** Sum numeric fields */
41
+ $sum?: (keyof T extends infer K ? K extends keyof T ? T[K] extends number ? K : never : never : never)[];
42
+ /** Calculate trend slope for numeric fields */
43
+ $trend?: (keyof T extends infer K ? K extends keyof T ? T[K] extends number ? K : never : never : never)[];
44
+ }
45
+ /**
46
+ * Calculates mathematical operations on an array of objects with optional grouping
47
+ * Supports statistical operations like sum, average, count, etc. with grouping capability
48
+ * @param operations - Mathematical operations to perform on data fields
49
+ * @param pgroupBy - Array of field names to group by (empty array for no grouping)
50
+ * @param inData - Input data array to process
51
+ * @param appendOperationToField - Whether to append operation name to result field names
52
+ * @returns Aggregated data with calculated values
53
+ * @example
54
+ * ```ts
55
+ * // Sales data aggregation
56
+ * const sales = [
57
+ * { region: 'North', product: 'Laptop', amount: 1000, quantity: 2 },
58
+ * { region: 'North', product: 'Mouse', amount: 50, quantity: 5 },
59
+ * { region: 'South', product: 'Laptop', amount: 1200, quantity: 3 }
60
+ * ]
61
+ *
62
+ * // Group by region and calculate totals
63
+ * const regionTotals = calculateAggregations(
64
+ * { $sum: ['amount', 'quantity'], $avg: ['amount'] },
65
+ * ['region'],
66
+ * sales
67
+ * )
68
+ * // Result: [
69
+ * // { region: 'North', amount$sum: 1050, quantity$sum: 7, amount$avg: 525 },
70
+ * // { region: 'South', amount$sum: 1200, quantity$sum: 3, amount$avg: 1200 }
71
+ * // ]
72
+ *
73
+ * // Overall totals (no grouping)
74
+ * const totals = calculateAggregations(
75
+ * { $sum: ['amount'], $count: ['product'], $countUniq: ['region'] },
76
+ * [],
77
+ * sales,
78
+ * false
79
+ * )
80
+ * // Result: { amount: 2250, product: 3, region: 2 }
81
+ * ```
82
+ */
83
+ declare const calculateAggregations: (operations: IMathOp, pgroupBy: string[], inData: any[], appendOperationToField?: boolean) => any;
84
+ /**
85
+ * Calculates the slope of a linear trend line using least squares regression
86
+ *
87
+ * Computes the "rise over run" coefficient that best fits the data points.
88
+ * Uses the least squares method to find the line y = mx + b, returning only m (slope).
89
+ *
90
+ * Slope interpretation:
91
+ * - **Positive slope**: Y increases as X increases (upward trend)
92
+ * - **Negative slope**: Y decreases as X increases (downward trend)
93
+ * - **Zero slope**: No trend, flat line
94
+ * - **Magnitude**: How steep the trend is (larger = steeper)
95
+ *
96
+ * Algorithm (Least Squares):
97
+ * 1. Calculate Σx, Σy, Σx², Σxy
98
+ * 2. Compute slope: m = (n·Σxy - Σx·Σy) / (n·Σx² - (Σx)²)
99
+ * 3. Handle division by zero (constant x values)
100
+ * 4. Round to 1 decimal place
101
+ *
102
+ * @param y - Dependent variable values (response variable)
103
+ * @param x - Independent variable values (predictor variable)
104
+ * @returns Slope value rounded to 1 decimal (0 if denominator is zero)
105
+ *
106
+ * @example
107
+ * ```typescript
108
+ * // Basic trend slope calculation
109
+ * const sales = [100, 120, 140, 160, 180]
110
+ * const months = [1, 2, 3, 4, 5]
111
+ * calculateTrendSlope(sales, months) // 20.0 (sales increase 20 units/month)
112
+ *
113
+ * const declining = [100, 90, 80, 70, 60]
114
+ * calculateTrendSlope(declining, months) // -10.0 (decreasing 10 units/month)
115
+ *
116
+ * const flat = [100, 100, 100, 100, 100]
117
+ * calculateTrendSlope(flat, months) // 0.0 (no trend)
118
+ * ```
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * // Real-world: Sales forecasting and trend analysis
123
+ * interface MonthlySales {
124
+ * month: number
125
+ * revenue: number
126
+ * }
127
+ *
128
+ * function analyzeSalesTrend(data: MonthlySales[]): void {
129
+ * const months = data.map(d => d.month)
130
+ * const revenue = data.map(d => d.revenue)
131
+ * const slope = calculateTrendSlope(revenue, months)
132
+ *
133
+ * console.log(`📈 Sales Trend Analysis:`)
134
+ * console.log(` Slope: ${slope} per month`)
135
+ *
136
+ * if (slope > 0) {
137
+ * const annualGrowth = slope * 12
138
+ * console.log(`✅ Growing trend: $${annualGrowth.toLocaleString()}/year projected`)
139
+ * } else if (slope < 0) {
140
+ * console.log(`⚠️ Declining trend: ${slope} per month`)
141
+ * console.log(`Action: Investigate causes and intervene`)
142
+ * } else {
143
+ * console.log(`➡️ Flat trend: No significant growth or decline`)
144
+ * }
145
+ * }
146
+ *
147
+ * const salesData = [
148
+ * { month: 1, revenue: 50000 },
149
+ * { month: 2, revenue: 52000 },
150
+ * { month: 3, revenue: 54000 },
151
+ * { month: 4, revenue: 56000 }
152
+ * ]
153
+ * analyzeSalesTrend(salesData)
154
+ * // Slope: 2000 per month
155
+ * // ✅ Growing: $24,000/year projected
156
+ * ```
157
+ *
158
+ * @example
159
+ * ```typescript
160
+ * // Real-world: User engagement trending
161
+ * function trackUserEngagement(dailyActiveUsers: number[]): string {
162
+ * const days = Array.from({ length: dailyActiveUsers.length }, (_, i) => i + 1)
163
+ * const slope = calculateTrendSlope(dailyActiveUsers, days)
164
+ *
165
+ * const avgUsers = dailyActiveUsers.reduce((a, b) => a + b) / dailyActiveUsers.length
166
+ * const changePercent = ((slope * 30) / avgUsers) * 100
167
+ *
168
+ * if (changePercent > 5) {
169
+ * return `🚀 Strong growth: ${changePercent.toFixed(1)}% monthly increase`
170
+ * } else if (changePercent < -5) {
171
+ * return `📉 Declining: ${changePercent.toFixed(1)}% monthly decrease (ALERT!)`
172
+ * } else {
173
+ * return `➡️ Stable: ${changePercent.toFixed(1)}% monthly change`
174
+ * }
175
+ * }
176
+ *
177
+ * const dau = [1000, 1020, 1050, 1080, 1100, 1120, 1150]
178
+ * trackUserEngagement(dau)
179
+ * // "🚀 Strong growth: 12.8% monthly increase"
180
+ * ```
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * // Real-world: Server response time degradation detection
185
+ * function monitorPerformanceDegradation(
186
+ * responseTimes: number[],
187
+ * timestamps: number[]
188
+ * ): void {
189
+ * const slope = calculateTrendSlope(responseTimes, timestamps)
190
+ *
191
+ * console.log(`⏱️ Performance Trend: ${slope}ms per time unit`)
192
+ *
193
+ * if (slope > 5) {
194
+ * console.log('🚨 ALERT: Response times degrading')
195
+ * console.log(`Degradation rate: ${slope}ms per unit`)
196
+ * console.log('Action: Investigate server load, memory leaks, database queries')
197
+ * } else if (slope < -5) {
198
+ * console.log('✅ Performance improving')
199
+ * } else {
200
+ * console.log('➡️ Performance stable')
201
+ * }
202
+ * }
203
+ *
204
+ * const times = [120, 125, 135, 150, 170, 200]
205
+ * const hours = [1, 2, 3, 4, 5, 6]
206
+ * monitorPerformanceDegradation(times, hours)
207
+ * // 🚨 ALERT: Response times degrading (16ms/hour)
208
+ * ```
209
+ *
210
+ * @example
211
+ * ```typescript
212
+ * // Real-world: Stock price momentum indicator
213
+ * function calculatePriceMomentum(prices: number[], days: number[]): string {
214
+ * const slope = calculateTrendSlope(prices, days)
215
+ * const avgPrice = prices.reduce((a, b) => a + b) / prices.length
216
+ * const momentum = (slope / avgPrice) * 100
217
+ *
218
+ * if (momentum > 1) {
219
+ * return `🟢 BULLISH (${momentum.toFixed(2)}% daily momentum)`
220
+ * } else if (momentum < -1) {
221
+ * return `🔴 BEARISH (${momentum.toFixed(2)}% daily momentum)`
222
+ * } else {
223
+ * return `🟡 NEUTRAL (${momentum.toFixed(2)}% daily momentum)`
224
+ * }
225
+ * }
226
+ *
227
+ * const stockPrices = [100, 102, 105, 108, 112, 115]
228
+ * const tradingDays = [1, 2, 3, 4, 5, 6]
229
+ * calculatePriceMomentum(stockPrices, tradingDays)
230
+ * // "🟢 BULLISH (2.86% daily momentum)"
231
+ * ```
232
+ *
233
+ * @example
234
+ * ```typescript
235
+ * // Edge cases
236
+ * calculateTrendSlope([1, 2, 3], [1, 2, 3]) // 1.0 (perfect positive correlation)
237
+ * calculateTrendSlope([3, 2, 1], [1, 2, 3]) // -1.0 (perfect negative)
238
+ * calculateTrendSlope([5, 5, 5], [1, 2, 3]) // 0.0 (flat line)
239
+ * calculateTrendSlope([1, 2, 3], [1, 1, 1]) // 0.0 (constant X, div by zero)
240
+ * calculateTrendSlope([10, 20], [1, 2]) // 10.0 (two points)
241
+ * ```
242
+ *
243
+ * @see {@link calculateCorrelation} for correlation strength (not just slope)
244
+ * @see {@link calculateAverage} for mean calculation
245
+ */
246
+ declare function calculateTrendSlope(y: number[], x: number[]): number;
247
+ /**
248
+ * Calculates the median of an array of numbers
249
+ *
250
+ * The median is the middle value in a sorted dataset. More robust than mean for
251
+ * skewed distributions or datasets with outliers. For even-length arrays, returns
252
+ * the average of the two middle values.
253
+ *
254
+ * Algorithm:
255
+ * 1. Sort array in ascending order
256
+ * 2. If odd length: return middle value
257
+ * 3. If even length: return average of two middle values
258
+ * 4. Empty array returns 0
259
+ *
260
+ * Use cases: Income analysis, response times, test scores, real estate prices
261
+ *
262
+ * @param values - Array of numbers to calculate median from (empty array returns 0)
263
+ * @returns Median value, or 0 if array is empty
264
+ *
265
+ * @example
266
+ * ```typescript
267
+ * // Odd number of values
268
+ * calculateMedian([1, 2, 3, 4, 5]) // 3 (middle value)
269
+ * calculateMedian([10, 5, 15]) // 10 (after sorting: [5, 10, 15])
270
+ *
271
+ * // Even number of values
272
+ * calculateMedian([1, 2, 3, 4]) // 2.5 (average of 2 and 3)
273
+ * calculateMedian([10, 20, 30, 40]) // 25 (average of 20 and 30)
274
+ *
275
+ * // Edge cases
276
+ * calculateMedian([]) // 0
277
+ * calculateMedian([42]) // 42
278
+ * calculateMedian([5, 5, 5]) // 5
279
+ *
280
+ * // Handles negative numbers
281
+ * calculateMedian([-10, -5, 0, 5, 10]) // 0
282
+ * ```
283
+ *
284
+ * @example
285
+ * ```typescript
286
+ * // Real-world: Analyze salary data (median better than mean for skewed data)
287
+ * const salaries = [30000, 35000, 40000, 45000, 50000, 250000]
288
+ *
289
+ * const mean = salaries.reduce((a, b) => a + b) / salaries.length
290
+ * const median = calculateMedian(salaries)
291
+ *
292
+ * console.log(`Mean: $${mean}`) // $75,000 (skewed by outlier)
293
+ * console.log(`Median: $${median}`) // $42,500 (more representative)
294
+ * ```
295
+ *
296
+ * @example
297
+ * ```typescript
298
+ * // Real-world: Website response time analysis
299
+ * const responseTimes = [120, 150, 180, 200, 220, 5000] // milliseconds
300
+ *
301
+ * const medianResponseTime = calculateMedian(responseTimes)
302
+ * console.log(`Median response: ${medianResponseTime}ms`) // 190ms
303
+ * // More useful than mean (946ms) which is skewed by one slow request
304
+ * ```
305
+ *
306
+ * @example
307
+ * ```typescript
308
+ * // Real-world: Grade distribution analysis
309
+ * const grades = [65, 70, 75, 80, 85, 90, 95]
310
+ *
311
+ * const median = calculateMedian(grades)
312
+ * const Q1 = calculatePercentile(grades, 25)
313
+ * const Q3 = calculatePercentile(grades, 75)
314
+ *
315
+ * console.log(`Median grade: ${median}`) // 80
316
+ * console.log(`25th percentile: ${Q1}`) // 70
317
+ * console.log(`75th percentile: ${Q3}`) // 90
318
+ * ```
319
+ *
320
+ * @see {@link calculateAverage} for arithmetic mean calculation
321
+ * @see {@link calculatePercentile} for other percentiles (median is 50th percentile)
322
+ * @see {@link calculateQuartiles} for Q1, Q2 (median), Q3
323
+ * @see {@link calculateMode} for most frequent value
324
+ */
325
+ declare const calculateMedian: (values: number[]) => number;
326
+ /**
327
+ * Calculates the mode (most frequent value) in an array of numbers
328
+ *
329
+ * The mode is the value that appears most frequently in a dataset. Returns null
330
+ * if the array is empty or if there are multiple modes (multimodal distribution).
331
+ *
332
+ * Algorithm:
333
+ * 1. Count frequency of each value using hash map
334
+ * 2. Track maximum frequency and corresponding value
335
+ * 3. Detect multimodal distributions (multiple values with same max frequency)
336
+ * 4. Return single mode or null if multimodal/empty
337
+ *
338
+ * Behavior:
339
+ * - Empty array → null
340
+ * - Single mode → returns that value
341
+ * - Multiple modes (tie) → null
342
+ * - All unique values → null (no mode)
343
+ *
344
+ * @param values - Array of numbers to analyze
345
+ * @returns The mode (most frequent value) or null if multimodal/empty
346
+ *
347
+ * @example
348
+ * ```typescript
349
+ * // Basic mode calculation
350
+ * calculateMode([1, 2, 2, 3, 3, 3, 4]) // 3 (appears 3 times)
351
+ * calculateMode([5, 5, 5, 1, 2, 3]) // 5 (most frequent)
352
+ * calculateMode([10, 20, 30]) // null (all unique, no mode)
353
+ * calculateMode([1, 1, 2, 2, 3]) // null (multimodal: 1 and 2 tie)
354
+ * calculateMode([]) // null (empty array)
355
+ * ```
356
+ *
357
+ * @example
358
+ * ```typescript
359
+ * // Real-world: Find most common response time in API logs
360
+ * const responseTimes = [
361
+ * 150, 200, 150, 300, 150, // 150ms appears most
362
+ * 200, 400, 150, 200, 150
363
+ * ]
364
+ * const commonResponseTime = calculateMode(responseTimes)
365
+ * // 150 (appears 5 times)
366
+ *
367
+ * if (commonResponseTime !== null) {
368
+ * console.log(`Most common response time: ${commonResponseTime}ms`)
369
+ * console.log('💡 Optimize for this latency profile')
370
+ * }
371
+ * ```
372
+ *
373
+ * @example
374
+ * ```typescript
375
+ * // Real-world: Detect most frequent error code in logs
376
+ * function analyzeErrorCodes(errorLogs: { code: number }[]): void {
377
+ * const codes = errorLogs.map(log => log.code)
378
+ * const mostFrequentCode = calculateMode(codes)
379
+ *
380
+ * if (mostFrequentCode !== null) {
381
+ * console.log(`🚨 Most frequent error: ${mostFrequentCode}`)
382
+ * console.log('Priority fix needed for this error type')
383
+ * } else {
384
+ * console.log('✅ No dominant error pattern (good distribution)')
385
+ * }
386
+ * }
387
+ *
388
+ * // Example usage
389
+ * const errors = [
390
+ * { code: 404 }, { code: 500 }, { code: 404 },
391
+ * { code: 404 }, { code: 503 }, { code: 404 }
392
+ * ]
393
+ * analyzeErrorCodes(errors)
394
+ * // 🚨 Most frequent error: 404
395
+ * ```
396
+ *
397
+ * @example
398
+ * ```typescript
399
+ * // Real-world: Find most popular product rating
400
+ * interface ProductReview {
401
+ * productId: string
402
+ * rating: number // 1-5 stars
403
+ * userId: string
404
+ * }
405
+ *
406
+ * function getMostCommonRating(reviews: ProductReview[]): string {
407
+ * const ratings = reviews.map(r => r.rating)
408
+ * const mode = calculateMode(ratings)
409
+ *
410
+ * if (mode === null) {
411
+ * return 'Ratings are evenly distributed'
412
+ * }
413
+ *
414
+ * const sentiment = mode >= 4 ? '😊 Positive' : mode <= 2 ? '😞 Negative' : '😐 Neutral'
415
+ * return `Most common rating: ${mode}⭐ (${sentiment})`
416
+ * }
417
+ *
418
+ * const reviews = [
419
+ * { productId: 'A1', rating: 5, userId: 'U1' },
420
+ * { productId: 'A1', rating: 5, userId: 'U2' },
421
+ * { productId: 'A1', rating: 4, userId: 'U3' },
422
+ * { productId: 'A1', rating: 5, userId: 'U4' }
423
+ * ]
424
+ *
425
+ * getMostCommonRating(reviews)
426
+ * // "Most common rating: 5⭐ (😊 Positive)"
427
+ * ```
428
+ *
429
+ * @example
430
+ * ```typescript
431
+ * // Real-world: Detect most frequent user action in analytics
432
+ * const userActions = [
433
+ * 'click', 'scroll', 'click', 'click',
434
+ * 'scroll', 'click', 'submit', 'click'
435
+ * ].map(action => {
436
+ * const actionMap = { click: 1, scroll: 2, submit: 3 }
437
+ * return actionMap[action as keyof typeof actionMap]
438
+ * })
439
+ *
440
+ * const dominantAction = calculateMode(userActions)
441
+ * const actionNames = { 1: 'click', 2: 'scroll', 3: 'submit' }
442
+ *
443
+ * if (dominantAction !== null) {
444
+ * console.log(`Most frequent action: ${actionNames[dominantAction as keyof typeof actionNames]}`)
445
+ * // "Most frequent action: click"
446
+ * }
447
+ * ```
448
+ *
449
+ * @example
450
+ * ```typescript
451
+ * // Edge cases
452
+ * calculateMode([42]) // 42 (single value)
453
+ * calculateMode([1, 1]) // 1 (all same)
454
+ * calculateMode([1, 2, 3, 4, 5]) // null (all unique)
455
+ * calculateMode([1, 1, 2, 2]) // null (bimodal)
456
+ * calculateMode([1, 1, 1, 2, 2, 2]) // null (bimodal tie)
457
+ * calculateMode([NaN, NaN, 1]) // NaN (NaN counted as value)
458
+ * calculateMode([Infinity, Infinity]) // Infinity
459
+ * ```
460
+ *
461
+ * @see {@link calculateMedian} for middle value (resistant to outliers)
462
+ * @see {@link calculateAverage} for mean value
463
+ * @see {@link calculateStandardDeviation} for data spread measurement
464
+ */
465
+ declare const calculateMode: (values: number[]) => number | null;
466
+ /**
467
+ * Calculates the standard deviation of an array of numbers
468
+ *
469
+ * Measures the amount of variation or dispersion in a dataset. Low standard deviation
470
+ * means values are close to the mean; high standard deviation means values are spread out.
471
+ *
472
+ * Algorithm:
473
+ * 1. Calculate mean (average)
474
+ * 2. Calculate squared differences from mean
475
+ * 3. Calculate variance (average of squared differences)
476
+ * 4. Return square root of variance
477
+ *
478
+ * Formula:
479
+ * - Population: σ = √(Σ(x - μ)² / N)
480
+ * - Sample: s = √(Σ(x - x̄)² / (N - 1))
481
+ *
482
+ * @param values - Array of numbers (empty array returns 0)
483
+ * @param sample - If true, uses sample standard deviation (N-1). If false, uses population (N). Default: false
484
+ * @returns Standard deviation, or 0 if array is empty
485
+ *
486
+ * @example
487
+ * ```typescript
488
+ * // Low standard deviation (values close together)
489
+ * calculateStandardDeviation([10, 11, 12, 13, 14])
490
+ * // ~1.41 (values tightly clustered)
491
+ *
492
+ * // High standard deviation (values spread out)
493
+ * calculateStandardDeviation([1, 5, 20, 50, 100])
494
+ * // ~35.96 (values widely dispersed)
495
+ *
496
+ * // Population vs Sample
497
+ * const data = [2, 4, 6, 8, 10]
498
+ * calculateStandardDeviation(data, false) // 2.83 (population)
499
+ * calculateStandardDeviation(data, true) // 3.16 (sample, Bessel's correction)
500
+ *
501
+ * // Edge cases
502
+ * calculateStandardDeviation([]) // 0
503
+ * calculateStandardDeviation([5]) // 0
504
+ * calculateStandardDeviation([5, 5, 5]) // 0 (no variation)
505
+ * ```
506
+ *
507
+ * @example
508
+ * ```typescript
509
+ * // Real-world: Quality control - manufacturing consistency
510
+ * const widgetWeights = [98.5, 99.2, 100.1, 99.8, 100.3, 98.9]
511
+ * const targetWeight = 100
512
+ *
513
+ * const mean = widgetWeights.reduce((a, b) => a + b) / widgetWeights.length
514
+ * const stdDev = calculateStandardDeviation(widgetWeights, true)
515
+ *
516
+ * console.log(`Mean weight: ${mean.toFixed(2)}g`)
517
+ * console.log(`Std deviation: ${stdDev.toFixed(2)}g`)
518
+ * // Low std dev = consistent manufacturing
519
+ * ```
520
+ *
521
+ * @example
522
+ * ```typescript
523
+ * // Real-world: Investment volatility analysis
524
+ * const monthlyReturns = [2.3, -1.5, 4.2, 0.8, -2.1, 3.5, 1.2] // %
525
+ *
526
+ * const avgReturn = monthlyReturns.reduce((a, b) => a + b) / monthlyReturns.length
527
+ * const volatility = calculateStandardDeviation(monthlyReturns, true)
528
+ *
529
+ * console.log(`Average return: ${avgReturn.toFixed(2)}%`)
530
+ * console.log(`Volatility (std dev): ${volatility.toFixed(2)}%`)
531
+ * // High volatility = riskier investment
532
+ * ```
533
+ *
534
+ * @example
535
+ * ```typescript
536
+ * // Real-world: Student performance analysis
537
+ * const testScores = [75, 82, 68, 90, 78, 85, 72, 88, 80, 77]
538
+ *
539
+ * const mean = testScores.reduce((a, b) => a + b) / testScores.length
540
+ * const stdDev = calculateStandardDeviation(testScores, true)
541
+ *
542
+ * // Identify outliers (beyond 2 standard deviations)
543
+ * const outliers = testScores.filter(score =>
544
+ * Math.abs(score - mean) > 2 * stdDev
545
+ * )
546
+ *
547
+ * console.log(`Mean: ${mean.toFixed(1)}`)
548
+ * console.log(`Std Dev: ${stdDev.toFixed(1)}`)
549
+ * console.log(`Outliers:`, outliers)
550
+ * ```
551
+ *
552
+ * @see {@link calculateVariance} for variance (σ²)
553
+ * @see {@link detectOutliers} for IQR-based outlier detection
554
+ * @see {@link calculateMedian} for central tendency (robust to outliers)
555
+ */
556
+ declare const calculateStandardDeviation: (values: number[], sample?: boolean) => number;
557
+ /**
558
+ * Calculates the variance of an array of numbers
559
+ *
560
+ * Variance measures how spread out numbers are from their mean (average).
561
+ * It's the average of squared differences from the mean. Higher variance = more spread.
562
+ *
563
+ * Algorithm:
564
+ * 1. Calculate mean (average) of all values
565
+ * 2. Compute squared difference from mean for each value: (value - mean)²
566
+ * 3. Sum all squared differences
567
+ * 4. Divide by N (population) or N-1 (sample) depending on `sample` flag
568
+ *
569
+ * Population vs Sample variance:
570
+ * - **Population (sample=false)**: Use when you have ALL data (divide by N)
571
+ * - **Sample (sample=true)**: Use when you have a subset (divide by N-1, Bessel's correction)
572
+ *
573
+ * @param values - Array of numbers to analyze
574
+ * @param sample - If true, uses sample variance (N-1). If false, uses population variance (N). Default: false
575
+ * @returns Variance value (0 if empty array)
576
+ *
577
+ * @example
578
+ * ```typescript
579
+ * // Basic variance calculation
580
+ * calculateVariance([1, 2, 3, 4, 5]) // 2 (population variance)
581
+ * calculateVariance([1, 2, 3, 4, 5], true) // 2.5 (sample variance)
582
+ * calculateVariance([10, 10, 10, 10]) // 0 (no variance, all same)
583
+ * calculateVariance([1, 100]) // 2450.5 (high variance)
584
+ * calculateVariance([]) // 0 (empty array)
585
+ * ```
586
+ *
587
+ * @example
588
+ * ```typescript
589
+ * // Real-world: Analyze server response time consistency
590
+ * const responseTimes = [120, 150, 130, 145, 125, 140, 135] // milliseconds
591
+ * const variance = calculateVariance(responseTimes)
592
+ * const stdDev = Math.sqrt(variance)
593
+ *
594
+ * console.log(`Variance: ${variance.toFixed(2)}ms²`)
595
+ * console.log(`Std Dev: ${stdDev.toFixed(2)}ms`)
596
+ *
597
+ * if (stdDev < 20) {
598
+ * console.log('✅ Consistent performance')
599
+ * } else {
600
+ * console.log('⚠️ High variability - investigate outliers')
601
+ * }
602
+ * // Variance: 110.20ms²
603
+ * // Std Dev: 10.50ms
604
+ * // ✅ Consistent performance
605
+ * ```
606
+ *
607
+ * @example
608
+ * ```typescript
609
+ * // Real-world: Quality control in manufacturing
610
+ * interface Measurement {
611
+ * batchId: string
612
+ * weight: number // grams
613
+ * }
614
+ *
615
+ * function checkBatchQuality(measurements: Measurement[]): boolean {
616
+ * const weights = measurements.map(m => m.weight)
617
+ * const variance = calculateVariance(weights)
618
+ * const maxAcceptableVariance = 5 // Quality threshold
619
+ *
620
+ * if (variance <= maxAcceptableVariance) {
621
+ * console.log('✅ Batch passes quality control')
622
+ * console.log(`Variance: ${variance.toFixed(2)}g² (within tolerance)`)
623
+ * return true
624
+ * } else {
625
+ * console.log('❌ Batch REJECTED - excessive variance')
626
+ * console.log(`Variance: ${variance.toFixed(2)}g² (exceeds ${maxAcceptableVariance}g²)`)
627
+ * return false
628
+ * }
629
+ * }
630
+ *
631
+ * const batch = [
632
+ * { batchId: 'B001', weight: 100.2 },
633
+ * { batchId: 'B001', weight: 100.5 },
634
+ * { batchId: 'B001', weight: 99.8 },
635
+ * { batchId: 'B001', weight: 100.1 }
636
+ * ]
637
+ *
638
+ * checkBatchQuality(batch)
639
+ * // ✅ Batch passes quality control
640
+ * // Variance: 0.09g² (within tolerance)
641
+ * ```
642
+ *
643
+ * @example
644
+ * ```typescript
645
+ * // Real-world: Stock price volatility analysis
646
+ * function analyzeStockVolatility(prices: number[]): string {
647
+ * const variance = calculateVariance(prices, true) // Sample variance
648
+ * const stdDev = Math.sqrt(variance)
649
+ * const mean = prices.reduce((sum, p) => sum + p, 0) / prices.length
650
+ * const coefficientOfVariation = (stdDev / mean) * 100
651
+ *
652
+ * if (coefficientOfVariation < 5) {
653
+ * return `Low volatility (${coefficientOfVariation.toFixed(1)}% CV) - Stable stock`
654
+ * } else if (coefficientOfVariation < 15) {
655
+ * return `Moderate volatility (${coefficientOfVariation.toFixed(1)}% CV) - Normal fluctuation`
656
+ * } else {
657
+ * return `High volatility (${coefficientOfVariation.toFixed(1)}% CV) - Risky investment`
658
+ * }
659
+ * }
660
+ *
661
+ * const stockPrices = [100, 102, 98, 101, 99, 103, 97] // Daily closing prices
662
+ * analyzeStockVolatility(stockPrices)
663
+ * // "Moderate volatility (2.1% CV) - Normal fluctuation"
664
+ * ```
665
+ *
666
+ * @example
667
+ * ```typescript
668
+ * // Real-world: A/B test result significance
669
+ * function compareVariability(groupA: number[], groupB: number[]): void {
670
+ * const varA = calculateVariance(groupA, true)
671
+ * const varB = calculateVariance(groupB, true)
672
+ * const ratio = varA / varB
673
+ *
674
+ * console.log(`Group A variance: ${varA.toFixed(2)}`)
675
+ * console.log(`Group B variance: ${varB.toFixed(2)}`)
676
+ * console.log(`Variance ratio: ${ratio.toFixed(2)}`)
677
+ *
678
+ * if (ratio > 2 || ratio < 0.5) {
679
+ * console.log('⚠️ Groups have significantly different variability')
680
+ * console.log('Consider using Welch\'s t-test instead of Student\'s t-test')
681
+ * } else {
682
+ * console.log('✅ Groups have similar variability')
683
+ * }
684
+ * }
685
+ *
686
+ * const conversionRatesA = [0.12, 0.15, 0.13, 0.14, 0.12]
687
+ * const conversionRatesB = [0.18, 0.22, 0.19, 0.21, 0.20]
688
+ *
689
+ * compareVariability(conversionRatesA, conversionRatesB)
690
+ * // Group A variance: 0.00013
691
+ * // Group B variance: 0.00025
692
+ * // Variance ratio: 0.52
693
+ * // ✅ Groups have similar variability
694
+ * ```
695
+ *
696
+ * @example
697
+ * ```typescript
698
+ * // Edge cases
699
+ * calculateVariance([5]) // 0 (single value)
700
+ * calculateVariance([5], true) // NaN (sample size 1, division by 0)
701
+ * calculateVariance([1, 1, 1]) // 0 (no variation)
702
+ * calculateVariance([0, 0, 0]) // 0 (all zeros)
703
+ * calculateVariance([-5, 0, 5]) // 16.67 (symmetric around 0)
704
+ * calculateVariance([1e10, 1e10 + 1]) // 0.25 (large numbers)
705
+ * ```
706
+ *
707
+ * @see {@link calculateStandardDeviation} for square root of variance (same units as data)
708
+ * @see {@link calculateIQR} for robust spread measure (resistant to outliers)
709
+ * @see {@link detectOutliers} for finding extreme values
710
+ */
711
+ declare const calculateVariance: (values: number[], sample?: boolean) => number;
712
+ /**
713
+ * Calculates a specific percentile from an array of numbers
714
+ *
715
+ * Percentiles indicate the value below which a given percentage of observations fall.
716
+ * For example, the 75th percentile is the value below which 75% of the data lies.
717
+ *
718
+ * Algorithm:
719
+ * 1. Sort values in ascending order
720
+ * 2. Calculate position: (percentile / 100) × (n - 1)
721
+ * 3. If position is integer, return value at that index
722
+ * 4. Otherwise, interpolate between lower and upper values using linear interpolation
723
+ *
724
+ * Common percentiles:
725
+ * - 25th (Q1): First quartile
726
+ * - 50th (Q2): Median
727
+ * - 75th (Q3): Third quartile
728
+ * - 90th: Top 10% threshold
729
+ * - 95th: Top 5% threshold
730
+ * - 99th: Top 1% threshold
731
+ *
732
+ * @param values - Array of numbers to analyze
733
+ * @param percentile - Percentile to calculate (0-100)
734
+ * @returns Value at the specified percentile (0 if empty array)
735
+ * @throws {Error} If percentile is not between 0 and 100
736
+ *
737
+ * @example
738
+ * ```typescript
739
+ * // Basic percentile calculation
740
+ * const scores = [55, 60, 65, 70, 75, 80, 85, 90, 95, 100]
741
+ *
742
+ * calculatePercentile(scores, 25) // 66.25 (Q1 - 25% below this)
743
+ * calculatePercentile(scores, 50) // 77.5 (Median - 50% below this)
744
+ * calculatePercentile(scores, 75) // 88.75 (Q3 - 75% below this)
745
+ * calculatePercentile(scores, 90) // 95.5 (90% below this)
746
+ * calculatePercentile(scores, 100) // 100 (Maximum)
747
+ * calculatePercentile(scores, 0) // 55 (Minimum)
748
+ * ```
749
+ *
750
+ * @example
751
+ * ```typescript
752
+ * // Real-world: API response time SLA monitoring
753
+ * const responseTimes = [
754
+ * 120, 150, 180, 200, 250, 300, 350, 400, 450, 500,
755
+ * 600, 700, 800, 1000, 1200
756
+ * ]
757
+ *
758
+ * const p50 = calculatePercentile(responseTimes, 50) // Median
759
+ * const p95 = calculatePercentile(responseTimes, 95) // 95th percentile
760
+ * const p99 = calculatePercentile(responseTimes, 99) // 99th percentile
761
+ *
762
+ * console.log(`📊 Response Time SLA:`)
763
+ * console.log(` 50th (median): ${p50}ms`)
764
+ * console.log(` 95th: ${p95}ms`)
765
+ * console.log(` 99th: ${p99}ms`)
766
+ *
767
+ * if (p95 < 500) {
768
+ * console.log('✅ SLA met: 95% of requests under 500ms')
769
+ * } else {
770
+ * console.log(`⚠️ SLA breach: p95=${p95}ms exceeds 500ms target`)
771
+ * }
772
+ * ```
773
+ *
774
+ * @example
775
+ * ```typescript
776
+ * // Real-world: Grade distribution analysis
777
+ * function analyzeExamResults(scores: number[]): void {
778
+ * const p10 = calculatePercentile(scores, 10)
779
+ * const p25 = calculatePercentile(scores, 25)
780
+ * const p50 = calculatePercentile(scores, 50)
781
+ * const p75 = calculatePercentile(scores, 75)
782
+ * const p90 = calculatePercentile(scores, 90)
783
+ *
784
+ * console.log('📈 Exam Score Distribution:')
785
+ * console.log(` Bottom 10%: ≤ ${p10.toFixed(1)}`)
786
+ * console.log(` Q1 (25th): ${p25.toFixed(1)}`)
787
+ * console.log(` Median (50th): ${p50.toFixed(1)}`)
788
+ * console.log(` Q3 (75th): ${p75.toFixed(1)}`)
789
+ * console.log(` Top 10%: ≥ ${p90.toFixed(1)}`)
790
+ *
791
+ * // Identify struggling students
792
+ * if (p25 < 60) {
793
+ * console.log('⚠️ Warning: 25% of students scored below 60')
794
+ * console.log('Recommendation: Provide additional support')
795
+ * }
796
+ * }
797
+ *
798
+ * const examScores = [45, 52, 58, 63, 67, 72, 75, 78, 82, 85, 88, 92, 95]
799
+ * analyzeExamResults(examScores)
800
+ * ```
801
+ *
802
+ * @example
803
+ * ```typescript
804
+ * // Real-world: Server load capacity planning
805
+ * interface ServerMetrics {
806
+ * timestamp: Date
807
+ * cpuUsage: number // percentage
808
+ * }
809
+ *
810
+ * function determineCapacityThreshold(metrics: ServerMetrics[]): number {
811
+ * const cpuUsages = metrics.map(m => m.cpuUsage)
812
+ * const p95 = calculatePercentile(cpuUsages, 95)
813
+ *
814
+ * console.log(`Current p95 CPU usage: ${p95.toFixed(1)}%`)
815
+ *
816
+ * if (p95 > 80) {
817
+ * console.log('🚨 CRITICAL: Scale up immediately')
818
+ * return 100 // Emergency threshold
819
+ * } else if (p95 > 60) {
820
+ * console.log('⚠️ WARNING: Plan scaling in next 24h')
821
+ * return 80
822
+ * } else {
823
+ * console.log('✅ Healthy capacity')
824
+ * return 70
825
+ * }
826
+ * }
827
+ * ```
828
+ *
829
+ * @example
830
+ * ```typescript
831
+ * // Real-world: Income inequality analysis (Gini coefficient context)
832
+ * const householdIncomes = [
833
+ * 25000, 30000, 35000, 40000, 45000, 50000, 55000,
834
+ * 60000, 70000, 80000, 90000, 120000, 150000, 200000
835
+ * ]
836
+ *
837
+ * const p10 = calculatePercentile(householdIncomes, 10)
838
+ * const p50 = calculatePercentile(householdIncomes, 50)
839
+ * const p90 = calculatePercentile(householdIncomes, 90)
840
+ *
841
+ * const p90p10Ratio = p90 / p10
842
+ *
843
+ * console.log(`Income distribution:`)
844
+ * console.log(` Bottom 10%: ≤$${p10.toLocaleString()}`)
845
+ * console.log(` Median: $${p50.toLocaleString()}`)
846
+ * console.log(` Top 10%: ≥$${p90.toLocaleString()}`)
847
+ * console.log(` P90/P10 ratio: ${p90p10Ratio.toFixed(2)}x`)
848
+ *
849
+ * if (p90p10Ratio > 5) {
850
+ * console.log('⚠️ High income inequality detected')
851
+ * }
852
+ * ```
853
+ *
854
+ * @example
855
+ * ```typescript
856
+ * // Edge cases
857
+ * calculatePercentile([10], 50) // 10 (single value)
858
+ * calculatePercentile([1, 2, 3, 4], 0) // 1 (minimum)
859
+ * calculatePercentile([1, 2, 3, 4], 100) // 4 (maximum)
860
+ * calculatePercentile([], 50) // 0 (empty array)
861
+ * calculatePercentile([5, 5, 5], 75) // 5 (all same values)
862
+ *
863
+ * // Error cases
864
+ * calculatePercentile([1, 2, 3], -1) // throws Error
865
+ * calculatePercentile([1, 2, 3], 101) // throws Error
866
+ * ```
867
+ *
868
+ * @see {@link calculateQuartiles} for Q1, Q2, Q3 in one call
869
+ * @see {@link calculateIQR} for interquartile range (Q3 - Q1)
870
+ * @see {@link calculateMedian} for 50th percentile specifically
871
+ * @see {@link detectOutliers} for finding extreme values using IQR method
872
+ */
873
+ declare const calculatePercentile: (values: number[], percentile: number) => number;
874
+ /**
875
+ * Calculates quartiles (Q1, Q2, Q3) of an array of numbers
876
+ *
877
+ * Quartiles divide a sorted dataset into four equal parts. Returns the three cut points:
878
+ * - **Q1 (25th percentile)**: 25% of data below, 75% above
879
+ * - **Q2 (50th percentile)**: Median - 50% below, 50% above
880
+ * - **Q3 (75th percentile)**: 75% below, 25% above
881
+ *
882
+ * Useful for:
883
+ * - Box plot visualization
884
+ * - Outlier detection (IQR method)
885
+ * - Understanding data spread and skewness
886
+ * - Five-number summary (min, Q1, Q2, Q3, max)
887
+ *
888
+ * @param values - Array of numbers to analyze
889
+ * @returns Object with Q1, Q2 (median), Q3 values
890
+ *
891
+ * @example
892
+ * ```typescript
893
+ * // Basic quartiles
894
+ * const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
895
+ * calculateQuartiles(data)
896
+ * // { Q1: 3.25, Q2: 5.5, Q3: 7.75 }
897
+ * ```
898
+ *
899
+ * @example
900
+ * ```typescript
901
+ * // Real-world: Salary distribution analysis
902
+ * const salaries = [
903
+ * 30000, 35000, 40000, 45000, 50000, 55000, 60000,
904
+ * 65000, 70000, 80000, 90000, 120000
905
+ * ]
906
+ *
907
+ * const { Q1, Q2, Q3 } = calculateQuartiles(salaries)
908
+ *
909
+ * console.log(`📊 Salary Distribution:`)
910
+ * console.log(` Q1 (25th): $${Q1.toLocaleString()}`)
911
+ * console.log(` Q2 (Median): $${Q2.toLocaleString()}`)
912
+ * console.log(` Q3 (75th): $${Q3.toLocaleString()}`)
913
+ * console.log(` IQR: $${(Q3 - Q1).toLocaleString()}`)
914
+ * // Q1: $43,750, Q2: $57,500, Q3: $72,500, IQR: $28,750
915
+ * ```
916
+ *
917
+ * @example
918
+ * ```typescript
919
+ * // Real-world: Performance monitoring box plot
920
+ * function createBoxPlot(responseTimes: number[]): void {
921
+ * const { Q1, Q2, Q3 } = calculateQuartiles(responseTimes)
922
+ * const min = Math.min(...responseTimes)
923
+ * const max = Math.max(...responseTimes)
924
+ * const iqr = Q3 - Q1
925
+ *
926
+ * console.log('📦 Response Time Box Plot:')
927
+ * console.log(` Min: ${min}ms`)
928
+ * console.log(` Q1: ${Q1}ms ├───┐`)
929
+ * console.log(` Q2: ${Q2}ms │ █ │ (median)`)
930
+ * console.log(` Q3: ${Q3}ms └───┤`)
931
+ * console.log(` Max: ${max}ms`)
932
+ * console.log(` IQR: ${iqr}ms (middle 50%)`)
933
+ * }
934
+ *
935
+ * const times = [120, 150, 180, 200, 220, 250, 300, 350, 400]
936
+ * createBoxPlot(times)
937
+ * ```
938
+ *
939
+ * @see {@link calculatePercentile} for calculating any percentile
940
+ * @see {@link calculateIQR} for interquartile range (Q3 - Q1)
941
+ * @see {@link detectOutliers} for outlier detection using quartiles
942
+ * @see {@link calculateMedian} for Q2 specifically
943
+ */
944
+ declare const calculateQuartiles: (values: number[]) => {
945
+ Q1: number;
946
+ Q2: number;
947
+ Q3: number;
948
+ };
949
+ /**
950
+ * Calculates the interquartile range (IQR) of an array of numbers
951
+ *
952
+ * IQR is the range of the middle 50% of data, calculated as Q3 - Q1.
953
+ * It's a robust measure of statistical dispersion, resistant to outliers.
954
+ *
955
+ * IQR interpretation:
956
+ * - **Small IQR**: Data tightly clustered around median (low variability)
957
+ * - **Large IQR**: Data widely spread (high variability)
958
+ * - **IQR = 0**: All middle 50% values identical
959
+ *
960
+ * Key uses:
961
+ * - Outlier detection (values outside Q1 - 1.5×IQR to Q3 + 1.5×IQR)
962
+ * - Box plot whiskers calculation
963
+ * - Robust alternative to standard deviation (less affected by extremes)
964
+ *
965
+ * @param values - Array of numbers to analyze
966
+ * @returns Interquartile range (Q3 - Q1)
967
+ *
968
+ * @example
969
+ * ```typescript
970
+ * // Basic IQR calculation
971
+ * const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
972
+ * calculateIQR(data) // 4.5 (middle 50% spans 4.5 units)
973
+ *
974
+ * const tightData = [10, 10.5, 11, 11.5, 12]
975
+ * calculateIQR(tightData) // 1 (low variability)
976
+ *
977
+ * const spreadData = [10, 20, 30, 40, 50, 60, 70, 80, 90]
978
+ * calculateIQR(spreadData) // 40 (high variability)
979
+ * ```
980
+ *
981
+ * @example
982
+ * ```typescript
983
+ * // Real-world: Compare consistency between two groups
984
+ * const teamA_responseTimes = [100, 110, 120, 130, 140, 150]
985
+ * const teamB_responseTimes = [80, 120, 130, 140, 180, 250]
986
+ *
987
+ * const iqrA = calculateIQR(teamA_responseTimes) // 30ms
988
+ * const iqrB = calculateIQR(teamB_responseTimes) // 60ms
989
+ *
990
+ * console.log(`Team A IQR: ${iqrA}ms (consistent)`)
991
+ * console.log(`Team B IQR: ${iqrB}ms (inconsistent)`)
992
+ *
993
+ * if (iqrB > iqrA * 1.5) {
994
+ * console.log('⚠️ Team B shows high variability - investigate')
995
+ * }
996
+ * ```
997
+ *
998
+ * @example
999
+ * ```typescript
1000
+ * // Real-world: Quality control tolerance check
1001
+ * function checkProductQuality(measurements: number[]): boolean {
1002
+ * const iqr = calculateIQR(measurements)
1003
+ * const maxAllowedIQR = 5 // mm tolerance
1004
+ *
1005
+ * console.log(`IQR: ${iqr.toFixed(2)}mm`)
1006
+ *
1007
+ * if (iqr <= maxAllowedIQR) {
1008
+ * console.log('✅ Manufacturing process within tolerance')
1009
+ * return true
1010
+ * } else {
1011
+ * console.log(`❌ IQR ${iqr}mm exceeds ${maxAllowedIQR}mm tolerance`)
1012
+ * console.log('Action: Recalibrate machinery')
1013
+ * return false
1014
+ * }
1015
+ * }
1016
+ *
1017
+ * const partLengths = [99.8, 100.0, 100.1, 100.2, 100.3]
1018
+ * checkProductQuality(partLengths)
1019
+ * ```
1020
+ *
1021
+ * @see {@link calculateQuartiles} for Q1, Q2, Q3 values
1022
+ * @see {@link detectOutliers} for IQR-based outlier detection
1023
+ * @see {@link calculateStandardDeviation} for parametric dispersion measure
1024
+ */
1025
+ declare const calculateIQR: (values: number[]) => number;
1026
+ /**
1027
+ * Detects outliers using the IQR (Interquartile Range) method
1028
+ *
1029
+ * Identifies values that fall outside the "normal" range defined by quartiles.
1030
+ * Uses Tukey's fences method, commonly used in box plots.
1031
+ *
1032
+ * Algorithm:
1033
+ * 1. Calculate Q1, Q3, and IQR (Q3 - Q1)
1034
+ * 2. Compute lower fence: Q1 - (multiplier × IQR)
1035
+ * 3. Compute upper fence: Q3 + (multiplier × IQR)
1036
+ * 4. Values outside fences are outliers
1037
+ *
1038
+ * Common multipliers:
1039
+ * - **1.5** (default): Standard outliers (Tukey's rule)
1040
+ * - **3.0**: Extreme outliers only (more conservative)
1041
+ *
1042
+ * @param values - Array of numbers to analyze
1043
+ * @param multiplier - IQR multiplier for fence calculation (default: 1.5)
1044
+ * @returns Array of outlier values
1045
+ *
1046
+ * @example
1047
+ * ```typescript
1048
+ * // Basic outlier detection
1049
+ * const data = [10, 12, 14, 15, 16, 18, 20, 22, 100]
1050
+ * detectOutliers(data) // [100] (extreme high value)
1051
+ *
1052
+ * const normal = [10, 12, 14, 15, 16, 18, 20, 22, 24]
1053
+ * detectOutliers(normal) // [] (no outliers)
1054
+ *
1055
+ * const withExtremes = [1, 10, 12, 14, 15, 16, 18, 20, 100]
1056
+ * detectOutliers(withExtremes) // [1, 100] (both low and high outliers)
1057
+ * ```
1058
+ *
1059
+ * @example
1060
+ * ```typescript
1061
+ * // Real-world: Detect anomalous response times
1062
+ * function analyzeResponseTimes(times: number[]): void {
1063
+ * const outliers = detectOutliers(times)
1064
+ *
1065
+ * if (outliers.length === 0) {
1066
+ * console.log('✅ No anomalous response times detected')
1067
+ * return
1068
+ * }
1069
+ *
1070
+ * const { Q1, Q3 } = calculateQuartiles(times)
1071
+ * const iqr = Q3 - Q1
1072
+ *
1073
+ * console.log(`⚠️ Found ${outliers.length} outliers:`)
1074
+ * outliers.forEach(outlier => {
1075
+ * const severity = outlier > Q3 + 3 * iqr ? 'EXTREME' : 'MODERATE'
1076
+ * console.log(` - ${outlier}ms (${severity})`)
1077
+ * })
1078
+ *
1079
+ * console.log('Recommendation: Investigate these requests')
1080
+ * }
1081
+ *
1082
+ * const apiTimes = [100, 120, 130, 140, 150, 160, 180, 200, 5000]
1083
+ * analyzeResponseTimes(apiTimes)
1084
+ * // ⚠️ Found 1 outliers:
1085
+ * // - 5000ms (EXTREME)
1086
+ * ```
1087
+ *
1088
+ * @example
1089
+ * ```typescript
1090
+ * // Real-world: Fraud detection in transaction amounts
1091
+ * interface Transaction {
1092
+ * id: string
1093
+ * amount: number
1094
+ * userId: string
1095
+ * }
1096
+ *
1097
+ * function detectSuspiciousTransactions(
1098
+ * transactions: Transaction[]
1099
+ * ): Transaction[] {
1100
+ * const amounts = transactions.map(t => t.amount)
1101
+ * const outlierAmounts = detectOutliers(amounts, 3) // More conservative
1102
+ *
1103
+ * const suspicious = transactions.filter(t =>
1104
+ * outlierAmounts.includes(t.amount)
1105
+ * )
1106
+ *
1107
+ * if (suspicious.length > 0) {
1108
+ * console.log(`🚨 ${suspicious.length} suspicious transactions:`)
1109
+ * suspicious.forEach(t => {
1110
+ * console.log(` ID: ${t.id}, Amount: $${t.amount}, User: ${t.userId}`)
1111
+ * })
1112
+ * console.log('Action: Flag for manual review')
1113
+ * }
1114
+ *
1115
+ * return suspicious
1116
+ * }
1117
+ * ```
1118
+ *
1119
+ * @example
1120
+ * ```typescript
1121
+ * // Real-world: Sensor data cleaning
1122
+ * function cleanSensorReadings(readings: number[]): number[] {
1123
+ * const outliers = detectOutliers(readings)
1124
+ * const cleaned = readings.filter(r => !outliers.includes(r))
1125
+ *
1126
+ * console.log(`Original readings: ${readings.length}`)
1127
+ * console.log(`Outliers removed: ${outliers.length}`)
1128
+ * console.log(`Cleaned readings: ${cleaned.length}`)
1129
+ *
1130
+ * if (outliers.length > readings.length * 0.1) {
1131
+ * console.log('⚠️ Warning: >10% outliers - sensor malfunction?')
1132
+ * }
1133
+ *
1134
+ * return cleaned
1135
+ * }
1136
+ *
1137
+ * const tempReadings = [20.1, 20.5, 20.8, 21.0, 85.0, 20.9, 21.2]
1138
+ * const clean = cleanSensorReadings(tempReadings)
1139
+ * // Original: 7, Outliers: 1 (85.0°C), Cleaned: 6
1140
+ * ```
1141
+ *
1142
+ * @example
1143
+ * ```typescript
1144
+ * // Comparing multipliers
1145
+ * const data = [1, 5, 10, 12, 14, 15, 16, 18, 20, 25, 100]
1146
+ *
1147
+ * detectOutliers(data, 1.5) // [1, 100] (standard)
1148
+ * detectOutliers(data, 3.0) // [100] (extreme only)
1149
+ * ```
1150
+ *
1151
+ * @see {@link calculateIQR} for IQR calculation
1152
+ * @see {@link calculateQuartiles} for quartile values
1153
+ * @see {@link calculateStandardDeviation} for parametric outlier detection (z-score method)
1154
+ */
1155
+ declare const detectOutliers: (values: number[], multiplier?: number) => number[];
1156
+ /**
1157
+ * Calculates Pearson correlation coefficient between two arrays of numbers
1158
+ *
1159
+ * Measures linear correlation between two variables. Returns value between -1 and +1:
1160
+ * - +1: Perfect positive correlation (as X increases, Y increases proportionally)
1161
+ * - 0: No linear correlation
1162
+ * - -1: Perfect negative correlation (as X increases, Y decreases proportionally)
1163
+ *
1164
+ * Formula (Pearson's r):
1165
+ * r = [n∑(xy) - ∑x∑y] / √{[n∑x² - (∑x)²][n∑y² - (∑y)²]}
1166
+ *
1167
+ * Use cases: A/B testing, feature selection, risk analysis, data validation
1168
+ *
1169
+ * ⚠️ NOTE: Measures LINEAR correlation only. May miss non-linear relationships.
1170
+ *
1171
+ * @param x - First array of numbers (must match length of y)
1172
+ * @param y - Second array of numbers (must match length of x)
1173
+ * @returns Correlation coefficient (-1 to +1), or 0 if arrays empty/mismatched/no variance
1174
+ *
1175
+ * @example
1176
+ * ```typescript
1177
+ * // Perfect positive correlation
1178
+ * calculateCorrelation([1, 2, 3, 4, 5], [2, 4, 6, 8, 10])
1179
+ * // 1.0 (perfect linear relationship: y = 2x)
1180
+ *
1181
+ * // Perfect negative correlation
1182
+ * calculateCorrelation([1, 2, 3, 4, 5], [10, 8, 6, 4, 2])
1183
+ * // -1.0 (perfect inverse relationship)
1184
+ *
1185
+ * // No correlation
1186
+ * calculateCorrelation([1, 2, 3, 4, 5], [5, 3, 5, 3, 5])
1187
+ * // ~0 (no linear relationship)
1188
+ *
1189
+ * // Moderate positive correlation
1190
+ * calculateCorrelation([1, 2, 3, 4, 5], [2, 3, 5, 7, 9])
1191
+ * // ~0.98 (strong positive correlation)
1192
+ *
1193
+ * // Edge cases
1194
+ * calculateCorrelation([], []) // 0
1195
+ * calculateCorrelation([1, 2], [1]) // 0 (length mismatch)
1196
+ * calculateCorrelation([5, 5, 5], [1, 2, 3]) // 0 (no variance in x)
1197
+ * ```
1198
+ *
1199
+ * @example
1200
+ * ```typescript
1201
+ * // Real-world: Analyze relationship between ad spend and sales
1202
+ * const adSpend = [1000, 1500, 2000, 2500, 3000, 3500] // $ thousands
1203
+ * const sales = [20, 28, 35, 42, 48, 55] // $ thousands
1204
+ *
1205
+ * const correlation = calculateCorrelation(adSpend, sales)
1206
+ * console.log(`Correlation: ${correlation.toFixed(3)}`)
1207
+ * // 0.998 (strong positive correlation - more ad spend → more sales)
1208
+ *
1209
+ * if (correlation > 0.7) {
1210
+ * console.log('✅ Strong relationship: Ad spend drives sales')
1211
+ * }
1212
+ * ```
1213
+ *
1214
+ * @example
1215
+ * ```typescript
1216
+ * // Real-world: Website traffic vs conversion rate analysis
1217
+ * const dailyVisitors = [1200, 1500, 1800, 2000, 2200, 2500]
1218
+ * const conversionRate = [3.2, 3.0, 2.9, 2.7, 2.6, 2.4]
1219
+ *
1220
+ * const correlation = calculateCorrelation(dailyVisitors, conversionRate)
1221
+ * console.log(`Correlation: ${correlation.toFixed(3)}`)
1222
+ * // -0.995 (strong negative correlation - more traffic → lower conversion %)
1223
+ * // Suggests traffic quality decreasing or server overload
1224
+ * ```
1225
+ *
1226
+ * @example
1227
+ * ```typescript
1228
+ * // Real-world: Feature selection for ML model
1229
+ * interface DataPoint {
1230
+ * temperature: number
1231
+ * humidity: number
1232
+ * windSpeed: number
1233
+ * rainfall: number
1234
+ * }
1235
+ *
1236
+ * const weatherData: DataPoint[] = [
1237
+ * { temperature: 25, humidity: 60, windSpeed: 10, rainfall: 0 },
1238
+ * { temperature: 30, humidity: 50, windSpeed: 15, rainfall: 2 },
1239
+ * { temperature: 20, humidity: 80, windSpeed: 5, rainfall: 10 },
1240
+ * // ... more data
1241
+ * ]
1242
+ *
1243
+ * // Find which features correlate with rainfall
1244
+ * const temp = weatherData.map(d => d.temperature)
1245
+ * const humidity = weatherData.map(d => d.humidity)
1246
+ * const wind = weatherData.map(d => d.windSpeed)
1247
+ * const rain = weatherData.map(d => d.rainfall)
1248
+ *
1249
+ * const correlations = {
1250
+ * temperature: calculateCorrelation(temp, rain),
1251
+ * humidity: calculateCorrelation(humidity, rain),
1252
+ * windSpeed: calculateCorrelation(wind, rain)
1253
+ * }
1254
+ *
1255
+ * console.log('Rainfall correlations:', correlations)
1256
+ * // { temperature: -0.45, humidity: 0.82, windSpeed: -0.23 }
1257
+ * // Humidity strongly predicts rainfall
1258
+ * ```
1259
+ *
1260
+ * @example
1261
+ * ```typescript
1262
+ * // Real-world: Portfolio diversification analysis
1263
+ * const stock1Returns = [2.3, -1.5, 4.2, 0.8, -2.1, 3.5]
1264
+ * const stock2Returns = [1.8, 2.1, -0.5, 1.2, 3.4, -1.8]
1265
+ *
1266
+ * const correlation = calculateCorrelation(stock1Returns, stock2Returns)
1267
+ * console.log(`Portfolio correlation: ${correlation.toFixed(3)}`)
1268
+ *
1269
+ * if (Math.abs(correlation) < 0.3) {
1270
+ * console.log('✅ Good diversification: Stocks move independently')
1271
+ * } else if (correlation > 0.7) {
1272
+ * console.log('⚠️ High correlation: Portfolio not diversified')
1273
+ * }
1274
+ * ```
1275
+ *
1276
+ * @see {@link calculateStandardDeviation} for measuring spread
1277
+ * @see {@link calculateTrendSlope} for linear regression slope
1278
+ * @see {@link https://en.wikipedia.org/wiki/Pearson_correlation_coefficient Pearson Correlation}
1279
+ */
1280
+ declare const calculateCorrelation: (x: number[], y: number[]) => number;
1281
+ /**
1282
+ * Calculates Net Present Value (NPV) of cash flows using discounted cash flow method
1283
+ *
1284
+ * Evaluates investment profitability by discounting future cash flows to present value.
1285
+ * Formula: NPV = CF₀ + CF₁/(1+r) + CF₂/(1+r)² + ... + CFₙ/(1+r)ⁿ
1286
+ *
1287
+ * Decision rules:
1288
+ * - NPV > 0: Investment profitable, accept project
1289
+ * - NPV = 0: Break-even, neutral decision
1290
+ * - NPV < 0: Investment unprofitable, reject project
1291
+ *
1292
+ * @param cashFlows - Array of cash flows [initial investment (negative), period 1, period 2, ...]
1293
+ * @param discountRate - Discount rate as decimal (e.g., 0.1 for 10% WACC/hurdle rate)
1294
+ * @returns Net Present Value in currency units
1295
+ *
1296
+ * @example
1297
+ * ```typescript
1298
+ * // Investment: -10000€ initial, then +3000€/year for 4 years
1299
+ * const npv = calculateNPV([-10000, 3000, 3000, 3000, 3000], 0.10)
1300
+ * console.log(npv) // 1509.67€ (profitable investment)
1301
+ *
1302
+ * // Real-world: Software project ROI analysis
1303
+ * const projectCashFlows = [
1304
+ * -50000, // Year 0: Development cost
1305
+ * 15000, // Year 1: Revenue
1306
+ * 20000, // Year 2: Revenue
1307
+ * 25000, // Year 3: Revenue
1308
+ * 30000 // Year 4: Revenue
1309
+ * ]
1310
+ * const wacc = 0.12 // 12% weighted average cost of capital
1311
+ * const projectNPV = calculateNPV(projectCashFlows, wacc)
1312
+ * if (projectNPV > 0) {
1313
+ * console.log(`✅ Project approved. NPV: ${projectNPV.toFixed(2)}€`)
1314
+ * }
1315
+ * ```
1316
+ *
1317
+ * @see {@link calculateIRR} for internal rate of return
1318
+ * @see {@link https://en.wikipedia.org/wiki/Net_present_value NPV Formula}
1319
+ */
1320
+ declare const calculateNPV: (cashFlows: number[], discountRate: number) => number;
1321
+ /**
1322
+ * Calculates Internal Rate of Return (IRR) using Newton-Raphson iterative method
1323
+ *
1324
+ * Finds discount rate that makes NPV = 0. IRR represents the annualized effective return rate.
1325
+ * Uses Newton-Raphson numerical method with configurable tolerance and iterations.
1326
+ *
1327
+ * Decision rules:
1328
+ * - IRR > Required Rate: Accept project (returns exceed cost of capital)
1329
+ * - IRR < Required Rate: Reject project (insufficient returns)
1330
+ *
1331
+ * @param cashFlows - Array of cash flows [initial investment, period 1, period 2, ...]
1332
+ * @param initialGuess - Starting guess for IRR (default: 0.1 = 10%)
1333
+ * @param maxIterations - Maximum iterations for convergence (default: 100)
1334
+ * @param tolerance - Convergence tolerance (default: 1e-6)
1335
+ * @returns Internal Rate of Return as decimal (e.g., 0.15 = 15% annual return)
1336
+ *
1337
+ * @example
1338
+ * ```typescript
1339
+ * // Investment: -1000€, returns +400€, +500€, +300€
1340
+ * const irr = calculateIRR([-1000, 400, 500, 300])
1341
+ * console.log(`${(irr * 100).toFixed(2)}%`) // ~16.17% annual return
1342
+ *
1343
+ * // Real-world: Compare to required return rate
1344
+ * const cashFlows = [-50000, 15000, 20000, 25000, 30000]
1345
+ * const irr = calculateIRR(cashFlows)
1346
+ * const requiredRate = 0.12 // 12% hurdle rate
1347
+ *
1348
+ * if (irr > requiredRate) {
1349
+ * console.log(`✅ IRR ${(irr*100).toFixed(1)}% exceeds ${(requiredRate*100)}% requirement`)
1350
+ * } else {
1351
+ * console.log(`❌ IRR ${(irr*100).toFixed(1)}% below ${(requiredRate*100)}% requirement`)
1352
+ * }
1353
+ * ```
1354
+ *
1355
+ * @see {@link calculateNPV} for net present value calculation
1356
+ * @see {@link https://en.wikipedia.org/wiki/Internal_rate_of_return IRR Formula}
1357
+ */
1358
+ declare const calculateIRR: (cashFlows: number[], initialGuess?: number, maxIterations?: number, tolerance?: number) => number;
1359
+ /**
1360
+ * Calculates future value (FV) with compound interest
1361
+ *
1362
+ * Formula: FV = PV × (1 + r)ⁿ
1363
+ *
1364
+ * @param presentValue - Initial investment amount
1365
+ * @param interestRate - Interest rate per period as decimal (e.g., 0.05 for 5%)
1366
+ * @param periods - Number of compounding periods
1367
+ * @returns Future value after n periods
1368
+ *
1369
+ * @example
1370
+ * ```typescript
1371
+ * // 1000€ at 5% annual interest for 10 years
1372
+ * const fv = calculateFutureValue(1000, 0.05, 10) // 1628.89€
1373
+ *
1374
+ * // Retirement planning: 10000€ invested for 30 years at 7%
1375
+ * const retirement = calculateFutureValue(10000, 0.07, 30) // 76,122.55€
1376
+ * ```
1377
+ *
1378
+ * @see {@link calculatePresentValue}
1379
+ */
1380
+ declare const calculateFutureValue: (presentValue: number, interestRate: number, periods: number) => number;
1381
+ /**
1382
+ * Calculates present value (PV) of future amount
1383
+ *
1384
+ * Formula: PV = FV / (1 + r)ⁿ
1385
+ *
1386
+ * @param futureValue - Future amount to discount
1387
+ * @param interestRate - Discount rate as decimal (e.g., 0.05 for 5%)
1388
+ * @param periods - Number of periods
1389
+ * @returns Present value today
1390
+ *
1391
+ * @example
1392
+ * ```typescript
1393
+ * // What's 10000€ in 5 years worth today at 6% discount?
1394
+ * const pv = calculatePresentValue(10000, 0.06, 5) // 7,472.58€
1395
+ * ```
1396
+ *
1397
+ * @see {@link calculateFutureValue}
1398
+ */
1399
+ declare const calculatePresentValue: (futureValue: number, interestRate: number, periods: number) => number;
1400
+ /**
1401
+ * Calculates periodic payment for annuity (loans, mortgages)
1402
+ *
1403
+ * Formula: PMT = PV × [r(1+r)ⁿ] / [(1+r)ⁿ - 1]
1404
+ *
1405
+ * @param presentValue - Loan/mortgage principal amount
1406
+ * @param interestRate - Interest rate per period as decimal
1407
+ * @param periods - Total number of payment periods
1408
+ * @returns Periodic payment amount
1409
+ *
1410
+ * @example
1411
+ * ```typescript
1412
+ * // 200000€ mortgage at 3% annual for 30 years (360 months)
1413
+ * const monthlyRate = 0.03 / 12 // 0.0025
1414
+ * const payment = calculateAnnuityPayment(200000, monthlyRate, 360) // 843.21€/month
1415
+ *
1416
+ * // Car loan: 25000€ at 5% for 5 years
1417
+ * const carPayment = calculateAnnuityPayment(25000, 0.05/12, 60) // 471.78€/month
1418
+ * ```
1419
+ */
1420
+ declare const calculateAnnuityPayment: (presentValue: number, interestRate: number, periods: number) => number;
1421
+ /**
1422
+ * Normalizes an array of numbers to [0, 1] range using min-max normalization
1423
+ *
1424
+ * Transforms values to a common scale where:
1425
+ * - Minimum value → 0
1426
+ * - Maximum value → 1
1427
+ * - Other values → proportional between 0 and 1
1428
+ *
1429
+ * Formula: normalized = (value - min) / (max - min)
1430
+ *
1431
+ * Use cases:
1432
+ * - Machine learning feature scaling
1433
+ * - Comparing datasets with different scales
1434
+ * - Data visualization (heatmaps, gradients)
1435
+ * - Neural network input preprocessing
1436
+ *
1437
+ * @param values - Array of numbers to normalize
1438
+ * @returns Array normalized to [0, 1] range (empty array returns [], all equal returns all 0s)
1439
+ *
1440
+ * @example
1441
+ * ```typescript
1442
+ * // Basic normalization
1443
+ * normalizeToRange([10, 20, 30, 40, 50])
1444
+ * // [0, 0.25, 0.5, 0.75, 1]
1445
+ *
1446
+ * normalizeToRange([100, 200, 150])
1447
+ * // [0, 1, 0.5]
1448
+ *
1449
+ * normalizeToRange([5, 5, 5])
1450
+ * // [0, 0, 0] (all equal, no range)
1451
+ *
1452
+ * normalizeToRange([])
1453
+ * // [] (empty array)
1454
+ * ```
1455
+ *
1456
+ * @example
1457
+ * ```typescript
1458
+ * // Real-world: Student grade normalization for comparison
1459
+ * interface StudentScore {
1460
+ * name: string
1461
+ * rawScore: number
1462
+ * }
1463
+ *
1464
+ * function normalizeScores(students: StudentScore[]): void {
1465
+ * const rawScores = students.map(s => s.rawScore)
1466
+ * const normalized = normalizeToRange(rawScores)
1467
+ *
1468
+ * students.forEach((student, i) => {
1469
+ * const normalizedScore = (normalized[i] * 100).toFixed(1)
1470
+ * console.log(`${student.name}: ${student.rawScore} → ${normalizedScore}%`)
1471
+ * })
1472
+ * }
1473
+ *
1474
+ * normalizeScores([
1475
+ * { name: 'Alice', rawScore: 85 },
1476
+ * { name: 'Bob', rawScore: 72 },
1477
+ * { name: 'Charlie', rawScore: 95 }
1478
+ * ])
1479
+ * // Alice: 85 → 56.5%
1480
+ * // Bob: 72 → 0.0%
1481
+ * // Charlie: 95 → 100.0%
1482
+ * ```
1483
+ *
1484
+ * @example
1485
+ * ```typescript
1486
+ * // Real-world: Sensor data visualization (temperature heatmap)
1487
+ * function generateHeatmapColors(temperatures: number[]): string[] {
1488
+ * const normalized = normalizeToRange(temperatures)
1489
+ *
1490
+ * return normalized.map(value => {
1491
+ * const intensity = Math.round(value * 255)
1492
+ * return `rgb(${intensity}, 0, ${255 - intensity})`
1493
+ * })
1494
+ * }
1495
+ *
1496
+ * const temps = [18, 22, 25, 30, 35]
1497
+ * generateHeatmapColors(temps)
1498
+ * // ['rgb(0, 0, 255)', 'rgb(60, 0, 195)', ...]
1499
+ * // Blue (cold) → Red (hot)
1500
+ * ```
1501
+ *
1502
+ * @example
1503
+ * ```typescript
1504
+ * // Real-world: ML feature scaling for neural network
1505
+ * interface HouseData {
1506
+ * sqft: number // 500-5000
1507
+ * price: number // 100000-1000000
1508
+ * bedrooms: number // 1-6
1509
+ * }
1510
+ *
1511
+ * function prepareMLFeatures(houses: HouseData[]): number[][] {
1512
+ * const sqfts = normalizeToRange(houses.map(h => h.sqft))
1513
+ * const prices = normalizeToRange(houses.map(h => h.price))
1514
+ * const bedrooms = normalizeToRange(houses.map(h => h.bedrooms))
1515
+ *
1516
+ * return sqfts.map((_, i) => [sqfts[i], prices[i], bedrooms[i]])
1517
+ * }
1518
+ *
1519
+ * // All features now in [0, 1] range for training
1520
+ * ```
1521
+ *
1522
+ * @see {@link scaleToRange} for normalizing to custom [min, max] range
1523
+ * @see {@link calculateStandardDeviation} for z-score normalization alternative
1524
+ */
1525
+ declare const normalizeToRange: (values: number[]) => number[];
1526
+ /**
1527
+ * Scales an array of numbers to a custom [min, max] range
1528
+ *
1529
+ * Transforms values to specified range while preserving proportions.
1530
+ * Uses min-max normalization internally, then scales to target range.
1531
+ *
1532
+ * Formula:
1533
+ * 1. Normalize to [0, 1]: norm = (value - min) / (max - min)
1534
+ * 2. Scale to [minRange, maxRange]: scaled = minRange + norm × (maxRange - minRange)
1535
+ *
1536
+ * Use cases:
1537
+ * - Image pixel values (0-255)
1538
+ * - Audio amplitude (-1 to 1)
1539
+ * - Progress bars (0-100%)
1540
+ * - Rating systems (1-5 stars)
1541
+ *
1542
+ * @param values - Array of numbers to scale
1543
+ * @param minRange - Target minimum value
1544
+ * @param maxRange - Target maximum value
1545
+ * @returns Array scaled to [minRange, maxRange]
1546
+ *
1547
+ * @example
1548
+ * ```typescript
1549
+ * // Basic scaling
1550
+ * scaleToRange([10, 20, 30, 40, 50], 0, 100)
1551
+ * // [0, 25, 50, 75, 100]
1552
+ *
1553
+ * scaleToRange([1, 2, 3, 4, 5], 1, 5)
1554
+ * // [1, 2, 3, 4, 5] (already in range)
1555
+ *
1556
+ * scaleToRange([0, 0.5, 1], 0, 255)
1557
+ * // [0, 127.5, 255] (grayscale pixel values)
1558
+ * ```
1559
+ *
1560
+ * @example
1561
+ * ```typescript
1562
+ * // Real-world: Convert arbitrary scores to 1-5 star rating
1563
+ * function convertToStarRating(scores: number[]): number[] {
1564
+ * const stars = scaleToRange(scores, 1, 5)
1565
+ * return stars.map(s => Math.round(s * 2) / 2) // Round to 0.5
1566
+ * }
1567
+ *
1568
+ * const reviewScores = [45, 67, 89, 92, 100]
1569
+ * convertToStarRating(reviewScores)
1570
+ * // [1, 2.5, 4, 4.5, 5]
1571
+ * ```
1572
+ *
1573
+ * @example
1574
+ * ```typescript
1575
+ * // Real-world: Progress bar percentage
1576
+ * function calculateProgress(completedTasks: number[]): number[] {
1577
+ * return scaleToRange(completedTasks, 0, 100).map(p => Math.round(p))
1578
+ * }
1579
+ *
1580
+ * const tasksCompleted = [2, 5, 8, 10]
1581
+ * calculateProgress(tasksCompleted)
1582
+ * // [0, 38, 75, 100] (percentage progress)
1583
+ * ```
1584
+ *
1585
+ * @example
1586
+ * ```typescript
1587
+ * // Real-world: Audio normalization to [-1, 1] range
1588
+ * function normalizeAudioSamples(samples: number[]): Float32Array {
1589
+ * const normalized = scaleToRange(samples, -1, 1)
1590
+ * return new Float32Array(normalized)
1591
+ * }
1592
+ *
1593
+ * const audioData = [0, 1000, 2000, 3000, 4000]
1594
+ * normalizeAudioSamples(audioData)
1595
+ * // Float32Array [-1, -0.5, 0, 0.5, 1]
1596
+ * ```
1597
+ *
1598
+ * @example
1599
+ * ```typescript
1600
+ * // Real-world: Sensor calibration to voltage range
1601
+ * interface SensorReading {
1602
+ * timestamp: Date
1603
+ * rawValue: number
1604
+ * }
1605
+ *
1606
+ * function calibrateSensor(readings: SensorReading[]): number[] {
1607
+ * const rawValues = readings.map(r => r.rawValue)
1608
+ * // Calibrate to 0-5V range
1609
+ * return scaleToRange(rawValues, 0, 5)
1610
+ * }
1611
+ *
1612
+ * const sensorData = [
1613
+ * { timestamp: new Date(), rawValue: 100 },
1614
+ * { timestamp: new Date(), rawValue: 300 },
1615
+ * { timestamp: new Date(), rawValue: 500 }
1616
+ * ]
1617
+ * calibrateSensor(sensorData)
1618
+ * // [0, 2.5, 5] volts
1619
+ * ```
1620
+ *
1621
+ * @see {@link normalizeToRange} for [0, 1] normalization
1622
+ */
1623
+ declare const scaleToRange: (values: number[], minRange: number, maxRange: number) => number[];
1624
+ /**
1625
+ * Calculates histogram by dividing data into equal-width bins
1626
+ *
1627
+ * Groups values into intervals (bins) and counts frequency in each bin.
1628
+ * Useful for understanding data distribution, finding patterns, and visualization.
1629
+ *
1630
+ * Algorithm:
1631
+ * 1. Find min/max values
1632
+ * 2. Calculate bin width: (max - min) / bins
1633
+ * 3. Create bins with ranges [start, end)
1634
+ * 4. Count values in each bin
1635
+ * 5. Last bin includes max value (closed interval)
1636
+ *
1637
+ * @param values - Array of numbers to analyze
1638
+ * @param bins - Number of bins/intervals to divide data into
1639
+ * @returns Array of objects with {range: [min, max], count: frequency}
1640
+ *
1641
+ * @example
1642
+ * ```typescript
1643
+ * // Basic histogram
1644
+ * const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
1645
+ * calculateHistogram(data, 5)
1646
+ * // [
1647
+ * // { range: [1, 2.8], count: 2 },
1648
+ * // { range: [2.8, 4.6], count: 2 },
1649
+ * // { range: [4.6, 6.4], count: 2 },
1650
+ * // { range: [6.4, 8.2], count: 2 },
1651
+ * // { range: [8.2, 10], count: 2 }
1652
+ * // ]
1653
+ * ```
1654
+ *
1655
+ * @example
1656
+ * ```typescript
1657
+ * // Real-world: Response time distribution analysis
1658
+ * function analyzeResponseTimes(times: number[]): void {
1659
+ * const histogram = calculateHistogram(times, 5)
1660
+ *
1661
+ * console.log('📊 Response Time Distribution:')
1662
+ * histogram.forEach(({ range, count }) => {
1663
+ * const bar = '█'.repeat(count)
1664
+ * console.log(`${range[0]}-${range[1]}ms: ${bar} (${count})`)
1665
+ * })
1666
+ *
1667
+ * // Identify slow requests
1668
+ * const slowBin = histogram[histogram.length - 1]
1669
+ * if (slowBin.count > histogram.length * 0.1) {
1670
+ * console.log(`⚠️ Warning: ${slowBin.count} requests in slowest bin`)
1671
+ * }
1672
+ * }
1673
+ *
1674
+ * const responseTimes = [
1675
+ * 120, 150, 180, 200, 220,
1676
+ * 250, 300, 350, 400, 5000
1677
+ * ]
1678
+ * analyzeResponseTimes(responseTimes)
1679
+ * // 120-1096ms: ████████ (8)
1680
+ * // ...
1681
+ * // 4024-5000ms: █ (1)
1682
+ * // ⚠️ Warning: 1 requests in slowest bin
1683
+ * ```
1684
+ *
1685
+ * @example
1686
+ * ```typescript
1687
+ * // Real-world: Salary distribution for HR analysis
1688
+ * interface Employee {
1689
+ * name: string
1690
+ * salary: number
1691
+ * }
1692
+ *
1693
+ * function analyzeSalaryDistribution(employees: Employee[]): void {
1694
+ * const salaries = employees.map(e => e.salary)
1695
+ * const histogram = calculateHistogram(salaries, 4)
1696
+ *
1697
+ * console.log('💰 Salary Distribution:')
1698
+ * histogram.forEach(({ range, count }, i) => {
1699
+ * const percentage = ((count / employees.length) * 100).toFixed(1)
1700
+ * console.log(`Band ${i + 1}: $${range[0].toLocaleString()}-$${range[1].toLocaleString()}`)
1701
+ * console.log(` Employees: ${count} (${percentage}%)`)
1702
+ * })
1703
+ * }
1704
+ *
1705
+ * const employees = [
1706
+ * { name: 'Alice', salary: 50000 },
1707
+ * { name: 'Bob', salary: 60000 },
1708
+ * { name: 'Charlie', salary: 75000 },
1709
+ * { name: 'David', salary: 90000 },
1710
+ * { name: 'Eve', salary: 120000 }
1711
+ * ]
1712
+ * analyzeSalaryDistribution(employees)
1713
+ * // Band 1: $50,000-$67,500 (2 employees - 40%)
1714
+ * // Band 2: $67,500-$85,000 (1 employee - 20%)
1715
+ * // ...
1716
+ * ```
1717
+ *
1718
+ * @see {@link calculatePercentile} for quantile analysis
1719
+ * @see {@link calculateQuartiles} for quartile-based binning
1720
+ */
1721
+ declare const calculateHistogram: (values: number[], bins: number) => Array<{
1722
+ range: [number, number];
1723
+ count: number;
1724
+ }>;
1725
+ /**
1726
+ * Calculates Euclidean distance (straight-line distance) between two n-dimensional points
1727
+ *
1728
+ * Euclidean distance is the "ordinary" straight-line distance between two points.
1729
+ * Formula: √Σ(p1ᵢ - p2ᵢ)² for all dimensions
1730
+ *
1731
+ * Use cases:
1732
+ * - Machine learning (K-NN, K-Means clustering)
1733
+ * - Similarity measurement
1734
+ * - Computer vision (object detection)
1735
+ * - Geospatial calculations (2D/3D coordinates)
1736
+ *
1737
+ * @param point1 - First n-dimensional point [x, y, z, ...]
1738
+ * @param point2 - Second n-dimensional point [x, y, z, ...]
1739
+ * @returns Euclidean distance between the two points
1740
+ * @throws {Error} If points have different dimensions
1741
+ *
1742
+ * @example
1743
+ * ```typescript
1744
+ * // 2D distance (x, y coordinates)
1745
+ * calculateEuclideanDistance([0, 0], [3, 4]) // 5 (3-4-5 triangle)
1746
+ * calculateEuclideanDistance([1, 2], [4, 6]) // 5
1747
+ *
1748
+ * // 3D distance
1749
+ * calculateEuclideanDistance([0, 0, 0], [1, 1, 1]) // ~1.73 (√3)
1750
+ *
1751
+ * // High-dimensional (ML features)
1752
+ * calculateEuclideanDistance([1, 2, 3, 4], [2, 3, 4, 5]) // 2
1753
+ * ```
1754
+ *
1755
+ * @example
1756
+ * ```typescript
1757
+ * // Real-world: K-Nearest Neighbors classification
1758
+ * interface User {
1759
+ * age: number
1760
+ * income: number
1761
+ * }
1762
+ *
1763
+ * function findNearestUsers(target: User, candidates: User[], k: number): User[] {
1764
+ * const distances = candidates.map(candidate => ({
1765
+ * user: candidate,
1766
+ * distance: calculateEuclideanDistance(
1767
+ * [target.age, target.income],
1768
+ * [candidate.age, candidate.income]
1769
+ * )
1770
+ * }))
1771
+ *
1772
+ * return distances
1773
+ * .sort((a, b) => a.distance - b.distance)
1774
+ * .slice(0, k)
1775
+ * .map(d => d.user)
1776
+ * }
1777
+ *
1778
+ * const target = { age: 30, income: 50000 }
1779
+ * const users = [
1780
+ * { age: 28, income: 48000 },
1781
+ * { age: 45, income: 80000 },
1782
+ * { age: 32, income: 52000 }
1783
+ * ]
1784
+ * findNearestUsers(target, users, 2)
1785
+ * // Returns 2 closest users by age/income
1786
+ * ```
1787
+ *
1788
+ * @example
1789
+ * ```typescript
1790
+ * // Real-world: Product recommendation similarity
1791
+ * interface Product {
1792
+ * price: number
1793
+ * rating: number
1794
+ * reviews: number
1795
+ * }
1796
+ *
1797
+ * function findSimilarProducts(
1798
+ * current: Product,
1799
+ * catalog: Product[]
1800
+ * ): Product[] {
1801
+ * const similarities = catalog.map(product => {
1802
+ * const distance = calculateEuclideanDistance(
1803
+ * [current.price, current.rating * 20, Math.log(current.reviews)],
1804
+ * [product.price, product.rating * 20, Math.log(product.reviews)]
1805
+ * )
1806
+ * return { product, similarity: 1 / (1 + distance) }
1807
+ * })
1808
+ *
1809
+ * return similarities
1810
+ * .sort((a, b) => b.similarity - a.similarity)
1811
+ * .slice(0, 5)
1812
+ * .map(s => s.product)
1813
+ * }
1814
+ * ```
1815
+ *
1816
+ * @see {@link calculateManhattanDistance} for taxicab distance (sum of absolute differences)
1817
+ * @see {@link simpleKMeans} for K-Means clustering using Euclidean distance
1818
+ */
1819
+ declare const calculateEuclideanDistance: (point1: number[], point2: number[]) => number;
1820
+ /**
1821
+ * Calculates Manhattan distance (taxicab/city block distance) between two n-dimensional points
1822
+ *
1823
+ * Manhattan distance is the sum of absolute differences in each dimension.
1824
+ * Formula: Σ|p1ᵢ - p2ᵢ| for all dimensions
1825
+ *
1826
+ * Named after Manhattan grid layout where you can only travel along streets (not diagonally).
1827
+ * Often more appropriate than Euclidean for grid-based movement or high-dimensional data.
1828
+ *
1829
+ * Use cases:
1830
+ * - Grid-based pathfinding (chess, robots)
1831
+ * - High-dimensional ML (less affected by curse of dimensionality)
1832
+ * - City distance calculations (street blocks)
1833
+ * - Outlier detection in sparse data
1834
+ *
1835
+ * @param point1 - First n-dimensional point [x, y, z, ...]
1836
+ * @param point2 - Second n-dimensional point [x, y, z, ...]
1837
+ * @returns Manhattan distance between the two points
1838
+ * @throws {Error} If points have different dimensions
1839
+ *
1840
+ * @example
1841
+ * ```typescript
1842
+ * // 2D Manhattan distance
1843
+ * calculateManhattanDistance([0, 0], [3, 4]) // 7 (3 + 4)
1844
+ * calculateManhattanDistance([1, 2], [4, 6]) // 7 (3 + 4)
1845
+ *
1846
+ * // Compare with Euclidean
1847
+ * calculateEuclideanDistance([0, 0], [3, 4]) // 5
1848
+ * calculateManhattanDistance([0, 0], [3, 4]) // 7
1849
+ *
1850
+ * // 3D distance
1851
+ * calculateManhattanDistance([0, 0, 0], [1, 1, 1]) // 3 (1+1+1)
1852
+ * ```
1853
+ *
1854
+ * @example
1855
+ * ```typescript
1856
+ * // Real-world: City block distance (taxi routing)
1857
+ * interface Location {
1858
+ * avenue: number // East-West
1859
+ * street: number // North-South
1860
+ * }
1861
+ *
1862
+ * function calculateTaxiFare(from: Location, to: Location): number {
1863
+ * const blocks = calculateManhattanDistance(
1864
+ * [from.avenue, from.street],
1865
+ * [to.avenue, to.street]
1866
+ * )
1867
+ * const baseFare = 3.50
1868
+ * const perBlock = 0.70
1869
+ * return baseFare + blocks * perBlock
1870
+ * }
1871
+ *
1872
+ * const start = { avenue: 5, street: 10 }
1873
+ * const end = { avenue: 12, street: 20 }
1874
+ * calculateTaxiFare(start, end)
1875
+ * // Blocks: 17, Fare: $15.40
1876
+ * ```
1877
+ *
1878
+ * @example
1879
+ * ```typescript
1880
+ * // Real-world: Chess king moves (Chebyshev) vs rook moves (Manhattan)
1881
+ * function calculateRookMoves(from: [number, number], to: [number, number]): number {
1882
+ * // Rook can move straight, so Manhattan distance = moves needed
1883
+ * return calculateManhattanDistance(from, to)
1884
+ * }
1885
+ *
1886
+ * calculateRookMoves([0, 0], [3, 4]) // 7 moves minimum
1887
+ * ```
1888
+ *
1889
+ * @example
1890
+ * ```typescript
1891
+ * // Real-world: High-dimensional text similarity
1892
+ * function compareDocuments(doc1Vector: number[], doc2Vector: number[]): number {
1893
+ * // Manhattan often works better than Euclidean for sparse high-dim data
1894
+ * return calculateManhattanDistance(doc1Vector, doc2Vector)
1895
+ * }
1896
+ *
1897
+ * const doc1 = [0, 3, 0, 5, 0, 2] // Word frequency vector
1898
+ * const doc2 = [1, 2, 0, 4, 0, 3]
1899
+ * compareDocuments(doc1, doc2) // 5 (difference in word frequencies)
1900
+ * ```
1901
+ *
1902
+ * @see {@link calculateEuclideanDistance} for straight-line distance
1903
+ * @see {@link simpleKMeans} for clustering algorithm
1904
+ */
1905
+ declare const calculateManhattanDistance: (point1: number[], point2: number[]) => number;
1906
+ /**
1907
+ * Implements simple K-Means clustering algorithm
1908
+ *
1909
+ * Groups data points into K clusters by minimizing within-cluster variance.
1910
+ * Uses Euclidean distance and iterative centroid updates until convergence.
1911
+ *
1912
+ * Algorithm:
1913
+ * 1. Initialize K centroids randomly from data points
1914
+ * 2. Assign each point to nearest centroid (Euclidean distance)
1915
+ * 3. Recalculate centroids as mean of assigned points
1916
+ * 4. Repeat steps 2-3 until convergence or max iterations
1917
+ *
1918
+ * Limitations:
1919
+ * - Requires knowing K in advance
1920
+ * - Sensitive to initial centroid placement (random)
1921
+ * - Assumes spherical clusters
1922
+ * - Can get stuck in local minima
1923
+ *
1924
+ * @param points - Array of n-dimensional points to cluster
1925
+ * @param k - Number of clusters to create
1926
+ * @param maxIterations - Maximum iterations before stopping (default: 100)
1927
+ * @returns Object with {centroids: K cluster centers, clusters: array mapping point index → cluster ID}
1928
+ *
1929
+ * @example
1930
+ * ```typescript
1931
+ * // Basic 2D clustering
1932
+ * const points = [
1933
+ * [1, 1], [2, 1], [1, 2], // Cluster 1 (bottom-left)
1934
+ * [8, 8], [9, 8], [8, 9] // Cluster 2 (top-right)
1935
+ * ]
1936
+ *
1937
+ * const { centroids, clusters } = simpleKMeans(points, 2)
1938
+ * console.log(centroids) // [[1.33, 1.33], [8.33, 8.33]]
1939
+ * console.log(clusters) // [0, 0, 0, 1, 1, 1]
1940
+ * ```
1941
+ *
1942
+ * @example
1943
+ * ```typescript
1944
+ * // Real-world: Customer segmentation
1945
+ * interface Customer {
1946
+ * age: number
1947
+ * income: number
1948
+ * spendingScore: number
1949
+ * }
1950
+ *
1951
+ * function segmentCustomers(customers: Customer[], segments: number) {
1952
+ * const points = customers.map(c => [c.age, c.income / 1000, c.spendingScore])
1953
+ * const { centroids, clusters } = simpleKMeans(points, segments)
1954
+ *
1955
+ * const segmented = customers.map((customer, i) => ({
1956
+ * ...customer,
1957
+ * segment: clusters[i]
1958
+ * }))
1959
+ *
1960
+ * console.log('📊 Customer Segments:')
1961
+ * centroids.forEach((centroid, i) => {
1962
+ * const count = clusters.filter(c => c === i).length
1963
+ * console.log(`Segment ${i + 1}: ${count} customers`)
1964
+ * console.log(` Avg age: ${centroid[0].toFixed(1)}`)
1965
+ * console.log(` Avg income: $${(centroid[1] * 1000).toLocaleString()}`)
1966
+ * console.log(` Avg spending: ${centroid[2].toFixed(1)}/100`)
1967
+ * })
1968
+ *
1969
+ * return segmented
1970
+ * }
1971
+ * ```
1972
+ *
1973
+ * @example
1974
+ * ```typescript
1975
+ * // Real-world: Image color quantization (reduce colors)
1976
+ * function quantizeColors(pixels: [number, number, number][], colors: number) {
1977
+ * // Each pixel is [R, G, B]
1978
+ * const { centroids, clusters } = simpleKMeans(pixels, colors)
1979
+ *
1980
+ * // Replace each pixel with its cluster centroid color
1981
+ * return pixels.map((_, i) => {
1982
+ * const cluster = clusters[i]
1983
+ * return centroids[cluster].map(Math.round) as [number, number, number]
1984
+ * })
1985
+ * }
1986
+ *
1987
+ * // Reduce 16M colors to 8 dominant colors
1988
+ * const pixels: [number, number, number][] = [
1989
+ * [255, 100, 50], [250, 110, 55], // Similar reds
1990
+ * [50, 200, 100], [55, 210, 105] // Similar greens
1991
+ * ]
1992
+ * quantizeColors(pixels, 2)
1993
+ * // Groups similar colors into 2 clusters
1994
+ * ```
1995
+ *
1996
+ * @example
1997
+ * ```typescript
1998
+ * // Real-world: Anomaly detection in server metrics
1999
+ * interface ServerMetrics {
2000
+ * cpuUsage: number // 0-100%
2001
+ * memoryUsage: number // 0-100%
2002
+ * responseTime: number // ms
2003
+ * }
2004
+ *
2005
+ * function detectAnomalies(metrics: ServerMetrics[]): number[] {
2006
+ * const points = metrics.map(m => [
2007
+ * m.cpuUsage,
2008
+ * m.memoryUsage,
2009
+ * m.responseTime / 10 // Scale to similar range
2010
+ * ])
2011
+ *
2012
+ * const { centroids, clusters } = simpleKMeans(points, 3)
2013
+ *
2014
+ * // Find cluster with highest avg response time
2015
+ * const clusterAvgs = centroids.map(c => c[2] * 10)
2016
+ * const anomalyCluster = clusterAvgs.indexOf(Math.max(...clusterAvgs))
2017
+ *
2018
+ * // Return indices of anomalous metrics
2019
+ * return clusters
2020
+ * .map((cluster, i) => cluster === anomalyCluster ? i : -1)
2021
+ * .filter(i => i !== -1)
2022
+ * }
2023
+ * ```
2024
+ *
2025
+ * @see {@link calculateEuclideanDistance} for distance metric used
2026
+ * @see {@link normalizeToRange} for feature scaling before clustering
2027
+ */
2028
+ declare const simpleKMeans: (points: number[][], k: number, maxIterations?: number) => {
2029
+ centroids: number[][];
2030
+ clusters: number[];
2031
+ };
2032
+
2033
+ type math_IMathOp<T = any> = IMathOp<T>;
2034
+ declare const math_calculateAggregations: typeof calculateAggregations;
2035
+ declare const math_calculateAnnuityPayment: typeof calculateAnnuityPayment;
2036
+ declare const math_calculateCorrelation: typeof calculateCorrelation;
2037
+ declare const math_calculateEuclideanDistance: typeof calculateEuclideanDistance;
2038
+ declare const math_calculateFutureValue: typeof calculateFutureValue;
2039
+ declare const math_calculateHistogram: typeof calculateHistogram;
2040
+ declare const math_calculateIQR: typeof calculateIQR;
2041
+ declare const math_calculateIRR: typeof calculateIRR;
2042
+ declare const math_calculateManhattanDistance: typeof calculateManhattanDistance;
2043
+ declare const math_calculateMedian: typeof calculateMedian;
2044
+ declare const math_calculateMode: typeof calculateMode;
2045
+ declare const math_calculateNPV: typeof calculateNPV;
2046
+ declare const math_calculatePercentile: typeof calculatePercentile;
2047
+ declare const math_calculatePresentValue: typeof calculatePresentValue;
2048
+ declare const math_calculateQuartiles: typeof calculateQuartiles;
2049
+ declare const math_calculateStandardDeviation: typeof calculateStandardDeviation;
2050
+ declare const math_calculateTrendSlope: typeof calculateTrendSlope;
2051
+ declare const math_calculateVariance: typeof calculateVariance;
2052
+ declare const math_detectOutliers: typeof detectOutliers;
2053
+ declare const math_normalizeToRange: typeof normalizeToRange;
2054
+ declare const math_scaleToRange: typeof scaleToRange;
2055
+ declare const math_simpleKMeans: typeof simpleKMeans;
2056
+ declare namespace math {
2057
+ export { type math_IMathOp as IMathOp, math_calculateAggregations as calculateAggregations, math_calculateAnnuityPayment as calculateAnnuityPayment, math_calculateCorrelation as calculateCorrelation, math_calculateEuclideanDistance as calculateEuclideanDistance, math_calculateFutureValue as calculateFutureValue, math_calculateHistogram as calculateHistogram, math_calculateIQR as calculateIQR, math_calculateIRR as calculateIRR, math_calculateManhattanDistance as calculateManhattanDistance, math_calculateMedian as calculateMedian, math_calculateMode as calculateMode, math_calculateNPV as calculateNPV, math_calculatePercentile as calculatePercentile, math_calculatePresentValue as calculatePresentValue, math_calculateQuartiles as calculateQuartiles, math_calculateStandardDeviation as calculateStandardDeviation, math_calculateTrendSlope as calculateTrendSlope, math_calculateVariance as calculateVariance, math_detectOutliers as detectOutliers, math_normalizeToRange as normalizeToRange, math_scaleToRange as scaleToRange, math_simpleKMeans as simpleKMeans };
2058
+ }
2059
+
2060
+ export { type IMathOp as I, calculateTrendSlope as a, calculateMedian as b, calculateAggregations as c, calculateMode as d, calculateStandardDeviation as e, calculateVariance as f, calculatePercentile as g, calculateQuartiles as h, calculateIQR as i, detectOutliers as j, calculateCorrelation as k, calculateNPV as l, math as m, calculateIRR as n, calculateFutureValue as o, calculatePresentValue as p, calculateAnnuityPayment as q, normalizeToRange as r, scaleToRange as s, calculateHistogram as t, calculateEuclideanDistance as u, calculateManhattanDistance as v, simpleKMeans as w };