Compute the default set of or requested quantiles for a coverage.
A One-Pass Space-Efficient Algorithm for Finding Quantiles (1995) by Rakesh Agrawal, Arun Swami in Proc. 7th Intl. Conf. Management of Data (COMAD-95)
In the future, it may be worth exploring algorithms that don't require the size of the coverage
1017 {
1019 int init_quantiles = 0;
1020
1024 const uint32_t MAX_VALUES = 750;
1025
1026 uint8_t *
data = NULL;
1028 int isnodata = 0;
1029
1030 uint32_t a = 0;
1031 uint32_t i = 0;
1032 uint32_t j = 0;
1033 uint32_t k = 0;
1036 uint32_t z = 0;
1037 uint32_t idx = 0;
1038 uint32_t offset = 0;
1039 uint32_t diff = 0;
1040 uint8_t exists = 0;
1041
1042 uint32_t do_sample = 0;
1043 uint32_t sample_size = 0;
1044 uint32_t sample_per = 0;
1045 uint32_t sample_int = 0;
1046 int status;
1047
1049
1050 assert(NULL != band);
1051 assert(cov_count > 1);
1052 assert(NULL != rtn_count);
1054
1056 if (data == NULL) {
1057 rterror(
"rt_band_get_summary_stats: Cannot get band data");
1058 return NULL;
1059 }
1060
1062 exclude_nodata_value = 0;
1063 RASTER_DEBUGF(3,
"exclude_nodata_value = %d", exclude_nodata_value);
1064
1065
1066 if (NULL == *qlls) {
1067
1068 if (NULL == quantiles) {
1069
1070 if (quantiles_count < 2)
1071 quantiles_count = 5;
1072
1073 quantiles =
rtalloc(
sizeof(
double) * quantiles_count);
1074 init_quantiles = 1;
1075 if (NULL == quantiles) {
1076 rterror(
"rt_band_get_quantiles_stream: Could not allocate memory for quantile input");
1077 return NULL;
1078 }
1079
1080 quantiles_count--;
1081 for (i = 0; i <= quantiles_count; i++)
1082 quantiles[i] = ((double) i) / quantiles_count;
1083 quantiles_count++;
1084 }
1085
1086
1087 for (i = 0; i < quantiles_count; i++) {
1088 if (quantiles[i] < 0. || quantiles[i] > 1.) {
1089 rterror(
"rt_band_get_quantiles_stream: Quantile value not between 0 and 1");
1090 if (init_quantiles)
rtdealloc(quantiles);
1091 return NULL;
1092 }
1093 }
1094 quicksort(quantiles, quantiles + quantiles_count - 1);
1095
1096
1097 *qlls_count = quantiles_count * 2;
1100 if (NULL == *qlls) {
1101 rterror(
"rt_band_get_quantiles_stream: Could not allocate memory for quantile output");
1102 if (init_quantiles)
rtdealloc(quantiles);
1103 return NULL;
1104 }
1105
1106 j = (uint32_t) floor(MAX_VALUES / 100.) + 1;
1107 for (i = 0; i < *qlls_count; i++) {
1108 qll = &((*qlls)[i]);
1109 qll->
quantile = quantiles[(i * quantiles_count) / *qlls_count];
1115
1116
1118 if (NULL == qll->
index) {
1119 rterror(
"rt_band_get_quantiles_stream: Could not allocate memory for quantile output");
1120 if (init_quantiles)
rtdealloc(quantiles);
1121 return NULL;
1122 }
1125
1126
1127 if (!(i % 2)) {
1130 if (qll->
tau < 1) qll->
tau = 1;
1131 }
1132
1133 else {
1135 qll->
tau = cov_count - (*qlls)[i - 1].tau + 1;
1136 }
1137
1138 RASTER_DEBUGF(4,
"qll init: (algeq, quantile, count, tau, sum1, sum2) = (%d, %f, %d, %llu, %llu, %llu)",
1141 }
1142
1143 if (init_quantiles)
rtdealloc(quantiles);
1144 }
1145
1146
1147 if (
1148 (sample < 0 ||
FLT_EQ(sample, 0.0)) ||
1149 (sample > 1 ||
FLT_EQ(sample, 1.0))
1150 ) {
1151 do_sample = 0;
1152 sample = 1;
1153 }
1154 else
1155 do_sample = 1;
1157
1158
1159 if (!do_sample) {
1160 sample_size =
band->width *
band->height;
1161 sample_per =
band->height;
1162 }
1163
1164
1165
1166
1167
1168 else {
1169 sample_size = round((
band->width *
band->height) * sample);
1170 sample_per = round(sample_size /
band->width);
1171 sample_int = round(
band->height / sample_per);
1172 srand(time(NULL));
1173 }
1174 RASTER_DEBUGF(3,
"sampling %d of %d available pixels w/ %d per set"
1175 , sample_size, (
band->width *
band->height), sample_per);
1176
1177 for (x = 0, j = 0, k = 0;
x <
band->width;
x++) {
1179 diff = 0;
1180
1181
1183 RASTER_DEBUG(3,
"Skipping quantile calculation as band is NODATA");
1184 break;
1185 }
1186
1187 for (i = 0, z = 0; i < sample_per; i++) {
1188 if (do_sample != 1)
1190 else {
1191 offset = (rand() % sample_int) + 1;
1193 diff = sample_int - offset;
1194 }
1196 if (y >=
band->height || z > sample_per)
break;
1197
1199
1200 j++;
1201 if (status ==
ES_NONE && (!exclude_nodata_value || (exclude_nodata_value && !isnodata))) {
1202
1203
1204 for (a = 0; a < *qlls_count; a++) {
1205 qll = &((*qlls)[a]);
1206 qls = NULL;
1208 RASTER_DEBUGF(5,
"qll before: (algeq, quantile, count, tau, sum1, sum2) = (%d, %f, %d, %lld, %lld, %lld)",
1211
1212
1214 if (NULL != qll->
head) {
1215 if (value < qll->head->value)
1217 }
1218 else {
1223 }
1224
1226 continue;
1227 }
1229 if (NULL != qll->
head) {
1232 }
1233 else {
1238 }
1239
1241 continue;
1242 }
1243
1244
1245
1247 qle = NULL;
1248
1251
1252 else {
1255 }
1256
1257
1258 if (NULL != qle) {
1261
1264
1267 else
1269
1271 }
1272
1273 else if (qll->
count < MAX_VALUES) {
1275
1276
1277
1281 }
1282
1283 else
1285 if (NULL == qle) return NULL;
1289
1290
1291 if (NULL == qle->
prev)
1293
1294 if (NULL == qle->
next)
1296
1299 else
1301
1302
1304
1305 RASTER_DEBUGF(5,
"qle, prev, next, head, tail = %p, %p, %p, %p, %p", qle, qle->
prev, qle->
next, qll->
head, qll->
tail);
1306 }
1307
1308 else if (qll->
algeq) {
1310
1311 if (value < qll->head->value) {
1312
1315 }
1316 else {
1317
1318
1328
1329
1331
1335 }
1336
1337 else {
1340 }
1341 if (NULL == qle) return NULL;
1345
1346
1347 if (NULL == qle->
prev)
1349
1350 if (NULL == qle->
next)
1352
1354
1356
1358
1359 }
1360 }
1361 else {
1363 while (NULL != qle) {
1369 break;
1370 }
1371
1373 }
1374 }
1375 }
1376
1377 else {
1379
1381
1384 }
1385 else {
1386
1387
1398
1399
1401
1405 }
1406
1407 else {
1410 }
1411 if (NULL == qle) return NULL;
1415
1416
1417 if (NULL == qle->
prev)
1419
1420 if (NULL == qle->
next)
1422
1424
1426
1428
1429 }
1430 }
1431 else {
1433 while (NULL != qle) {
1439 break;
1440 }
1441
1443 }
1444 }
1445 }
1446
1449
1452
1461
1463 }
1464 else {
1471
1473 }
1474 }
1475
1476 else {
1478
1487 }
1488 else {
1495
1497 }
1498 }
1499 }
1500
1501 RASTER_DEBUGF(5,
"qll after: (algeq, quantile, count, tau, sum1, sum2) = (%d, %f, %d, %lld, %lld, %lld)",
1504 }
1505
1506 }
1507 else {
1508 RASTER_DEBUGF(5,
"skipping value at (x, y) = (%u, %lld)", x, y);
1509 }
1510
1511 z++;
1512 }
1513 }
1514
1515
1516 *rtn_count = *qlls_count / 2;
1518 if (NULL == rtn) return NULL;
1519
1521 for (i = 0, k = 0; i < *qlls_count; i++) {
1522 qll = &((*qlls)[i]);
1523
1524 exists = 0;
1525 for (x = 0;
x < k;
x++) {
1527 exists = 1;
1528 break;
1529 }
1530 }
1531 if (exists) continue;
1532
1533 RASTER_DEBUGF(5,
"qll: (algeq, quantile, count, tau, sum1, sum2) = (%d, %f, %d, %lld, %lld, %lld)",
1536
1539
1540
1541 if (qll->
head == NULL || qll->
tail == NULL)
1542 continue;
1543
1544
1547
1548 else
1550
1551 exists = 0;
1552 for (j = i + 1; j < *qlls_count; j++) {
1554
1555 RASTER_DEBUGF(5,
"qlls[%d]: (algeq, quantile, count, tau, sum1, sum2) = (%d, %f, %d, %lld, %lld, %lld)",
1556 j, (*qlls)[j].algeq, (*qlls)[j].quantile, (*qlls)[j].
count, (*qlls)[j].tau, (*qlls)[j].sum1, (*qlls)[j].sum2);
1557 RASTER_DEBUGF(5,
"qlls[%d]: (head, tail) = (%p, %p)", j, (*qlls)[j].head, (*qlls)[j].tail);
1558
1559 exists = 1;
1560 break;
1561 }
1562 }
1563
1564
1565 if (exists) {
1566 if ((*qlls)[j].algeq) {
1567 rtn[k].
value = ((qle->
value * qle->
count) + ((*qlls)[j].head->value * (*qlls)[j].head->count)) / (qle->
count + (*qlls)[j].head->count);
1568 RASTER_DEBUGF(5,
"qlls[%d].head: (value, count) = (%f, %d)", j, (*qlls)[j].head->value, (*qlls)[j].head->count);
1569 }
1570 else {
1571 rtn[k].
value = ((qle->
value * qle->
count) + ((*qlls)[j].tail->value * (*qlls)[j].tail->count)) / (qle->
count + (*qlls)[j].tail->count);
1572 RASTER_DEBUGF(5,
"qlls[%d].tail: (value, count) = (%f, %d)", j, (*qlls)[j].tail->value, (*qlls)[j].tail->count);
1573 }
1574 }
1575
1576 else {
1578 }
1581
1582 k++;
1583 }
1584
1586 return rtn;
1587}
void rterror(const char *fmt,...) __attribute__((format(printf
Wrappers used for reporting errors and info.
void * rtalloc(size_t size)
Wrappers used for managing memory.
#define RASTER_DEBUG(level, msg)
#define RASTER_DEBUGF(level, msg,...)
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
void * rt_band_get_data(rt_band band)
Get pointer to raster band data.
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
void rtdealloc(void *mem)
static struct quantile_llist_element * quantile_llist_index_search(struct quantile_llist *qll, double value, uint32_t *index)
static void quantile_llist_index_update(struct quantile_llist *qll, struct quantile_llist_element *qle, uint32_t idx)
static struct quantile_llist_element * quantile_llist_insert(struct quantile_llist_element *element, double value, uint32_t *idx)
static void quantile_llist_index_delete(struct quantile_llist *qll, struct quantile_llist_element *qle)
static struct quantile_llist_element * quantile_llist_search(struct quantile_llist_element *element, double needle)
static void quicksort(double *left, double *right)
static int quantile_llist_delete(struct quantile_llist_element *element)
static void quantile_llist_index_reset(struct quantile_llist *qll)
struct quantile_llist_element * prev
struct quantile_llist_element * next
struct quantile_llist_element * head
struct quantile_llist_element * tail
struct quantile_llist_index * index