Numeric Sort Order
Numeric Sort Order

Order records by numeric order without converting the text to a numeric value.


Declare (simple) numeric ordering field (numeric)
Field declaration
Segment Source
 113:   int numeric;                  /* Flag for numeric comparison.  Handle
 114:                                    strings of digits with optional decimal
 115:                                    point, but no exponential notation. */

Insert user message text
Text insertion
Segment Source
 230:   -n               compare according to string numerical value, imply -b\n\

Define fraccompare()
Function definition
Segment Source
 753: /* Compare strings A and B containing decimal fractions < 1.  Each string
 754:    should begin with a decimal point followed immediately by the digits
 755:    of the fraction.  Strings not of this form are considered to be zero. */
 756: 
 757: static int
 758: fraccompare (register const char *a, register const char *b)
 759: {
 760:   register int tmpa = *a;
 761:   register int tmpb = *b;
 762: 
 763:   if (tmpa == '.' && tmpb == '.')
 764:     {
 765:       do
 766:         tmpa = *++a, tmpb = *++b;
 767:       while (tmpa == tmpb && ISDIGIT (tmpa));
 768:       if (ISDIGIT (tmpa) && ISDIGIT (tmpb))
 769:         return tmpa - tmpb;
 770:       if (ISDIGIT (tmpa))
 771:         {
 772:           while (tmpa == '0')
 773:             tmpa = *++a;
 774:           if (ISDIGIT (tmpa))
 775:             return 1;
 776:           return 0;
 777:         }
 778:       if (ISDIGIT (tmpb))
 779:         {
 780:           while (tmpb == '0')
 781:             tmpb = *++b;
 782:           if (ISDIGIT (tmpb))
 783:             return -1;
 784:           return 0;
 785:         }
 786:       return 0;
 787:     }
 788:   else if (tmpa == '.')
 789:     {
 790:       do
 791:         tmpa = *++a;
 792:       while (tmpa == '0');
 793:       if (ISDIGIT (tmpa))
 794:         return 1;
 795:       return 0;
 796:     }
 797:   else if (tmpb == '.')
 798:     {
 799:       do
 800:         tmpb = *++b;
 801:       while (tmpb == '0');
 802:       if (ISDIGIT (tmpb))
 803:         return -1;
 804:       return 0;
 805:     }
 806:   return 0;
 807: }
 808: 

Define numcompare()
Function definition
Segment Source
 809: /* Compare strings A and B as numbers without explicitly converting them to
 810:    machine numbers.  Comparatively slow for short strings, but asymptotically
 811:    hideously fast. */
 812: 
 813: static int
 814: numcompare (register const char *a, register const char *b)
 815: {
 816:   register int tmpa, tmpb, loga, logb, tmp;
 817: 
 818:   tmpa = UCHAR (*a);
 819:   tmpb = UCHAR (*b);
 820: 
 821:   while (blanks[tmpa])
 822:     tmpa = UCHAR (*++a);
 823:   while (blanks[tmpb])
 824:     tmpb = UCHAR (*++b);
 825: 
 826:   if (tmpa == '-')
 827:     {
 828:       do
 829:         tmpa = *++a;
 830:       while (tmpa == '0');
 831:       if (tmpb != '-')
 832:         {
 833:           if (tmpa == '.')
 834:             do
 835:               tmpa = *++a;
 836:             while (tmpa == '0');
 837:           if (ISDIGIT (tmpa))
 838:             return -1;
 839:           while (tmpb == '0')
 840:             tmpb = *++b;
 841:           if (tmpb == '.')
 842:             do
 843:               tmpb = *++b;
 844:             while (tmpb == '0');
 845:           if (ISDIGIT (tmpb))
 846:             return -1;
 847:           return 0;
 848:         }
 849:       do
 850:         tmpb = *++b;
 851:       while (tmpb == '0');
 852: 
 853:       while (tmpa == tmpb && ISDIGIT (tmpa))
 854:         tmpa = *++a, tmpb = *++b;
 855: 
 856:       if ((tmpa == '.' && !ISDIGIT (tmpb))
 857:           || (tmpb == '.' && !ISDIGIT (tmpa)))
 858:         return -fraccompare (a, b);
 859: 
 860:       if (ISDIGIT (tmpa))
 861:         for (loga = 1; ISDIGIT (*++a); ++loga)
 862:           ;
 863:       else
 864:         loga = 0;
 865: 
 866:       if (ISDIGIT (tmpb))
 867:         for (logb = 1; ISDIGIT (*++b); ++logb)
 868:           ;
 869:       else
 870:         logb = 0;
 871: 
 872:       if ((tmp = logb - loga) != 0)
 873:         return tmp;
 874: 
 875:       if (!loga)
 876:         return 0;
 877: 
 878:       return tmpb - tmpa;
 879:     }
 880:   else if (tmpb == '-')
 881:     {
 882:       do
 883:         tmpb = *++b;
 884:       while (tmpb == '0');
 885:       if (tmpb == '.')
 886:         do
 887:           tmpb = *++b;
 888:         while (tmpb == '0');
 889:       if (ISDIGIT (tmpb))
 890:         return 1;
 891:       while (tmpa == '0')
 892:         tmpa = *++a;
 893:       if (tmpa == '.')
 894:         do
 895:           tmpa = *++a;
 896:         while (tmpa == '0');
 897:       if (ISDIGIT (tmpa))
 898:         return 1;
 899:       return 0;
 900:     }
 901:   else
 902:     {
 903:       while (tmpa == '0')
 904:         tmpa = *++a;
 905:       while (tmpb == '0')
 906:         tmpb = *++b;
 907: 
 908:       while (tmpa == tmpb && ISDIGIT (tmpa))
 909:         tmpa = *++a, tmpb = *++b;
 910: 
 911:       if ((tmpa == '.' && !ISDIGIT (tmpb))
 912:           || (tmpb == '.' && !ISDIGIT (tmpa)))
 913:         return fraccompare (a, b);
 914: 
 915:       if (ISDIGIT (tmpa))
 916:         for (loga = 1; ISDIGIT (*++a); ++loga)
 917:           ;
 918:       else
 919:         loga = 0;
 920: 
 921:       if (ISDIGIT (tmpb))
 922:         for (logb = 1; ISDIGIT (*++b); ++logb)
 923:           ;
 924:       else
 925:         logb = 0;
 926: 
 927:       if ((tmp = loga - logb) != 0)
 928:         return tmp;
 929: 
 930:       if (!loga)
 931:         return 0;
 932: 
 933:       return tmpa - tmpb;
 934:     }
 935: }
 936: 

Dispatch (simple) numeric compare
Code insertion
Segment Source
1049:       if (key->numeric)
1050:         {
1051:           if (*lima || *limb)
1052:             {
1053:               char savea = *lima, saveb = *limb;
1054: 
1055:               *lima = *limb = '\0';
1056:               diff = numcompare (texta, textb);
1057:               *lima = savea, *limb = saveb;
1058:             }
1059:           else
1060:             diff = numcompare (texta, textb);
1061: 
1062:           if (diff)
1063:             return key->reverse ? -diff : diff;
1064:           continue;
1065:         }

Parse NumOrder option (-n)
Code insertion
Segment Source
1694:         case 'n':
1695:           key->numeric = 1;
1696:           break;

Establish global sort options
Code modification
Segment Source
1773:   gkey.numeric =  gkey.general_numeric = gkey.month = gkey.reverse = 0;

Propogate global sort options
Segment Element
Code modification

2032:         && !key->skipeblanks && !key->month && !key->numeric

Segment Element
Code insertion

2040:         key->numeric = gkey.numeric;

Segment Element
Code modification

2046:                         || gkey.skipeblanks || gkey.month || gkey.numeric