*** ./src/backend/utils/adt/numeric.c.orig Sat Oct 15 11:49:29 2005 --- ./src/backend/utils/adt/numeric.c Mon Nov 7 14:26:04 2005 *************** *** 229,234 **** --- 229,238 ---- #define init_var(v) MemSetAligned(v, 0, sizeof(NumericVar)) + #define NUMERIC_DIGITS(num) ((NumericDigit *)(num)->n_data) + #define NUMERIC_NDIGITS(num) \ + (((num)->varlen - NUMERIC_HDRSZ) / sizeof(NumericDigit)) + static void alloc_var(NumericVar *var, int ndigits); static void free_var(NumericVar *var); static void zero_var(NumericVar *var); *************** *** 250,255 **** --- 254,263 ---- static int cmp_numerics(Numeric num1, Numeric num2); static int cmp_var(NumericVar *var1, NumericVar *var2); + static int cmp_var_common(const NumericDigit *var1digits, int var1ndigits, + int var1weight, int var1sign, + const NumericDigit *var2digits, int var2ndigits, + int var2weight, int var2sign); static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result); static void sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result); static void mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result, *************** *** 271,276 **** --- 279,288 ---- int rscale); static int cmp_abs(NumericVar *var1, NumericVar *var2); + static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, + int var1weight, + const NumericDigit *var2digits, int var2ndigits, + int var2weight); static void add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result); static void sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result); static void round_var(NumericVar *var, int rscale); *************** *** 1061,1079 **** } else { ! NumericVar arg1; ! NumericVar arg2; ! ! init_var(&arg1); ! init_var(&arg2); ! ! set_var_from_num(num1, &arg1); ! set_var_from_num(num2, &arg2); ! ! result = cmp_var(&arg1, &arg2); ! ! free_var(&arg1); ! free_var(&arg2); } return result; --- 1073,1082 ---- } else { ! result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1), ! num1->n_weight, NUMERIC_SIGN(num1), ! NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2), ! num2->n_weight, NUMERIC_SIGN(num2)); } return result; *************** *** 2588,2598 **** static void dump_numeric(const char *str, Numeric num) { ! NumericDigit *digits = (NumericDigit *) num->n_data; int ndigits; int i; ! ndigits = (num->varlen - NUMERIC_HDRSZ) / sizeof(NumericDigit); printf("%s: NUMERIC w=%d d=%d ", str, num->n_weight, NUMERIC_DSCALE(num)); switch (NUMERIC_SIGN(num)) --- 2591,2601 ---- static void dump_numeric(const char *str, Numeric num) { ! NumericDigit *digits = NUMERIC_DIGITS(num); int ndigits; int i; ! ndigits = NUMERIC_NDIGITS(num); printf("%s: NUMERIC w=%d d=%d ", str, num->n_weight, NUMERIC_DSCALE(num)); switch (NUMERIC_SIGN(num)) *************** *** 2892,2898 **** { int ndigits; ! ndigits = (num->varlen - NUMERIC_HDRSZ) / sizeof(NumericDigit); alloc_var(dest, ndigits); --- 2895,2901 ---- { int ndigits; ! ndigits = NUMERIC_NDIGITS(num); alloc_var(dest, ndigits); *************** *** 3388,3419 **** static int cmp_var(NumericVar *var1, NumericVar *var2) { ! if (var1->ndigits == 0) { ! if (var2->ndigits == 0) return 0; ! if (var2->sign == NUMERIC_NEG) return 1; return -1; } ! if (var2->ndigits == 0) { ! if (var1->sign == NUMERIC_POS) return 1; return -1; } ! if (var1->sign == NUMERIC_POS) { ! if (var2->sign == NUMERIC_NEG) return 1; ! return cmp_abs(var1, var2); } ! if (var2->sign == NUMERIC_POS) return -1; ! return cmp_abs(var2, var1); } --- 3391,3442 ---- static int cmp_var(NumericVar *var1, NumericVar *var2) { ! return cmp_var_common(var1->digits, var1->ndigits, ! var1->weight, var1->sign, ! var2->digits, var2->ndigits, ! var2->weight, var2->sign); ! } ! ! /* ! * cmp_var_common() - ! * ! * Main routine of cmp_var(). This function can be used by both ! * NumericVar and Numeric. ! */ ! static int ! cmp_var_common(const NumericDigit *var1digits, int var1ndigits, ! int var1weight, int var1sign, ! const NumericDigit *var2digits, int var2ndigits, ! int var2weight, int var2sign) ! { ! if (var1ndigits == 0) { ! if (var2ndigits == 0) return 0; ! if (var2sign == NUMERIC_NEG) return 1; return -1; } ! if (var2ndigits == 0) { ! if (var1sign == NUMERIC_POS) return 1; return -1; } ! if (var1sign == NUMERIC_POS) { ! if (var2sign == NUMERIC_NEG) return 1; ! return cmp_abs_common(var1digits, var1ndigits, var1weight, ! var2digits, var2ndigits, var2weight); } ! if (var2sign == NUMERIC_POS) return -1; ! return cmp_abs_common(var2digits, var2ndigits, var2weight, ! var1digits, var1ndigits, var1weight); } *************** *** 4808,4840 **** static int cmp_abs(NumericVar *var1, NumericVar *var2) { ! NumericDigit *var1digits = var1->digits; ! NumericDigit *var2digits = var2->digits; int i1 = 0; int i2 = 0; - int w1 = var1->weight; - int w2 = var2->weight; /* Check any digits before the first common digit */ ! while (w1 > w2 && i1 < var1->ndigits) { if (var1digits[i1++] != 0) return 1; ! w1--; } ! while (w2 > w1 && i2 < var2->ndigits) { if (var2digits[i2++] != 0) return -1; ! w2--; } /* At this point, either w1 == w2 or we've run out of digits */ ! if (w1 == w2) { ! while (i1 < var1->ndigits && i2 < var2->ndigits) { int stat = var1digits[i1++] - var2digits[i2++]; --- 4831,4874 ---- static int cmp_abs(NumericVar *var1, NumericVar *var2) { ! return cmp_abs_common(var1->digits, var1->ndigits, var1->weight, ! var2->digits, var2->ndigits, var2->weight); ! } ! ! /* ---------- ! * cmp_abs_common() - ! * ! * Main routine of cmp_abs(). This function can be used by both ! * NumericVar and Numeric. ! * ---------- ! */ ! static int ! cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, ! const NumericDigit *var2digits, int var2ndigits, int var2weight) ! { int i1 = 0; int i2 = 0; /* Check any digits before the first common digit */ ! while (var1weight > var2weight && i1 < var1ndigits) { if (var1digits[i1++] != 0) return 1; ! var1weight--; } ! while (var2weight > var1weight && i2 < var2ndigits) { if (var2digits[i2++] != 0) return -1; ! var2weight--; } /* At this point, either w1 == w2 or we've run out of digits */ ! if (var1weight == var2weight) { ! while (i1 < var1ndigits && i2 < var2ndigits) { int stat = var1digits[i1++] - var2digits[i2++]; *************** *** 4851,4862 **** * At this point, we've run out of digits on one side or the other; so any * remaining nonzero digits imply that side is larger */ ! while (i1 < var1->ndigits) { if (var1digits[i1++] != 0) return 1; } ! while (i2 < var2->ndigits) { if (var2digits[i2++] != 0) return -1; --- 4885,4896 ---- * At this point, we've run out of digits on one side or the other; so any * remaining nonzero digits imply that side is larger */ ! while (i1 < var1ndigits) { if (var1digits[i1++] != 0) return 1; } ! while (i2 < var2ndigits) { if (var2digits[i2++] != 0) return -1;