1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
/*-------------------------------------------------------------------------
*
* sort.c
* sort of data inside columns
*
* Portions Copyright (c) 2017-2026 Pavel Stehule
*
* IDENTIFICATION
* src/sort.c
*
*-------------------------------------------------------------------------
*/
#include <stdlib.h>
#include <string.h>
#include "pspg.h"
static inline int
signof(double n)
{
if (n < 0)
return -1;
else if (n > 0)
return 1;
else
return 0;
}
static int
compar_num_asc(const void *a, const void *b)
{
SortData *sda = (SortData *) a;
SortData *sdb = (SortData *) b;
if (sdb->info == INFO_DOUBLE)
{
if (sda->info == INFO_DOUBLE)
/*
* Without using signof function there is possible problem with
* mapping of 8bytes double to 4bytes int (the sign of result value
* after casting can be wrong).
*/
return signof(sda->d - sdb->d);
else
return 1;
}
else
{
if (sda->info == INFO_DOUBLE)
return -1;
else
return 0;
}
}
static int
compar_num_desc(const void *a, const void *b)
{
SortData *sda = (SortData *) a;
SortData *sdb = (SortData *) b;
if (sdb->info == INFO_DOUBLE)
{
if (sda->info == INFO_DOUBLE)
return signof(sdb->d - sda->d);
else
return 1;
}
else
{
if (sda->info == INFO_DOUBLE)
return -1;
else
return 0;
}
}
void
sort_column_num(SortData *sortbuf, int rows, bool desc)
{
qsort(sortbuf, rows, sizeof(SortData), desc ? compar_num_desc : compar_num_asc);
}
static int
compar_text_asc(const void *a, const void *b)
{
SortData *sda = (SortData *) a;
SortData *sdb = (SortData *) b;
if (sdb->info == INFO_STRXFRM)
{
if (sda->info == INFO_STRXFRM)
return strcmp(sda->strxfrm, sdb->strxfrm);
else
return 1;
}
else
{
if (sda->info == INFO_STRXFRM)
return -1;
else
return 0;
}
}
static int
compar_text_desc(const void *a, const void *b)
{
SortData *sda = (SortData *) a;
SortData *sdb = (SortData *) b;
if (sdb->info == INFO_STRXFRM)
{
if (sda->info == INFO_STRXFRM)
return strcmp(sdb->strxfrm, sda->strxfrm);
else
return 1;
}
else
{
if (sda->info == INFO_STRXFRM)
return -1;
else
return 0;
}
}
void
sort_column_text(SortData *sortbuf, int rows, bool desc)
{
qsort(sortbuf, rows, sizeof(SortData), desc ? compar_text_desc : compar_text_asc);
}
|