|
5 | 5 | *
|
6 | 6 | * 1998 Jan Wieck
|
7 | 7 | *
|
8 |
| - * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.39 2001/03/22 06:16:17 momjian Exp $ |
| 8 | + * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.40 2001/04/14 02:10:57 tgl Exp $ |
9 | 9 | *
|
10 | 10 | * ----------
|
11 | 11 | */
|
@@ -1134,7 +1134,6 @@ numeric_mod(PG_FUNCTION_ARGS)
|
1134 | 1134 |
|
1135 | 1135 | mod_var(&arg1, &arg2, &result);
|
1136 | 1136 |
|
1137 |
| - result.dscale = result.rscale; |
1138 | 1137 | res = make_result(&result);
|
1139 | 1138 |
|
1140 | 1139 | free_var(&result);
|
@@ -3281,29 +3280,42 @@ mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
|
3281 | 3280 | {
|
3282 | 3281 | NumericVar tmp;
|
3283 | 3282 | int save_global_rscale;
|
| 3283 | + int div_dscale; |
3284 | 3284 |
|
3285 | 3285 | init_var(&tmp);
|
3286 | 3286 |
|
3287 | 3287 | /* ---------
|
3288 | 3288 | * We do this using the equation
|
3289 | 3289 | * mod(x,y) = x - trunc(x/y)*y
|
3290 |
| - * We fiddle a bit with global_rscale to control result precision. |
| 3290 | + * We set global_rscale the same way numeric_div and numeric_mul do |
| 3291 | + * to get the right answer from the equation. The final result, |
| 3292 | + * however, need not be displayed to more precision than the inputs. |
3291 | 3293 | * ----------
|
3292 | 3294 | */
|
3293 | 3295 | save_global_rscale = global_rscale;
|
3294 |
| - global_rscale = var2->rscale + 2; |
| 3296 | + |
| 3297 | + div_dscale = MAX(var1->dscale + var2->dscale, NUMERIC_MIN_DISPLAY_SCALE); |
| 3298 | + div_dscale = MIN(div_dscale, NUMERIC_MAX_DISPLAY_SCALE); |
| 3299 | + global_rscale = MAX(var1->rscale + var2->rscale, |
| 3300 | + NUMERIC_MIN_RESULT_SCALE); |
| 3301 | + global_rscale = MAX(global_rscale, div_dscale + 4); |
| 3302 | + global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE); |
3295 | 3303 |
|
3296 | 3304 | div_var(var1, var2, &tmp);
|
3297 | 3305 |
|
| 3306 | + tmp.dscale = div_dscale; |
| 3307 | + |
3298 | 3308 | /* do trunc() by forgetting digits to the right of the decimal point */
|
3299 | 3309 | tmp.ndigits = MAX(0, MIN(tmp.ndigits, tmp.weight + 1));
|
3300 |
| - tmp.rscale = var2->rscale; |
3301 | 3310 |
|
3302 |
| - global_rscale = var2->rscale; |
| 3311 | + global_rscale = var2->rscale + tmp.rscale; |
| 3312 | + |
3303 | 3313 | mul_var(var2, &tmp, &tmp);
|
3304 | 3314 |
|
3305 | 3315 | sub_var(var1, &tmp, result);
|
3306 | 3316 |
|
| 3317 | + result->dscale = MAX(var1->dscale, var2->dscale); |
| 3318 | + |
3307 | 3319 | global_rscale = save_global_rscale;
|
3308 | 3320 | free_var(&tmp);
|
3309 | 3321 | }
|
|
0 commit comments