Hi

2015-12-26 21:44 GMT+01:00 Pavel Stehule <pavel.steh...@gmail.com>:

> Hi
>
> 2015-11-19 3:58 GMT+01:00 Marko Tiikkaja <ma...@joh.to>:
>
>> Hi,
>>
>> Here's a patch for the second function suggested in
>> 5643125e.1030...@joh.to.  This is my first patch trying to do anything
>> with numerics, so please be gentle.  I'm sure it's full of stupid.
>>
>> January's commit fest, feedback welcome, yada yada..
>>
>
> I am looking on this patch and I don't understand to formula
>
> dscale = (ndigits - arg.weight - 1) * DEC_DIGITS;
>
> the following rule is valid
>
> DEC_DIGITS * ndigits >= dscale + arg.weight + 1
>
> so dscale should be calculated like
>
> dscale <= DEC_DIGITS * ndigits - arg.weight - 1
>
> ?
>
> but your formula is correct and working. Can you explain it?
>

I understand to it now. I didn't catch the semantic of arg.weight well.

So I am sending a review of this patch.

1. There is not any objection against this feature. I am thinking so it is
good idea, and this mechanism can be used more often in other routines by
default. But it is different topic.

2. The implementation is simple, without any possible side effects,
performance impacts, etc

3. The patch is clean, small, it does what is expected.

4. There is good enough doc and regress tests

5. The patch respects PostgreSQL formatting - original version is maybe too
compact, I am sending a little bit edited code with few more empty lines.

6. All regress tests was passed

I'll mark this patch as ready for commiter

Regards

Pavel



>
> Regards
>
> Pavel
>
>
>
>
>
>
>>
>>
>> .m
>>
>
>
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
new file mode 100644
index e08bf60..e417c5b
*** a/doc/src/sgml/func.sgml
--- b/doc/src/sgml/func.sgml
***************
*** 782,787 ****
--- 782,800 ----
        <row>
         <entry>
          <indexterm>
+          <primary>numeric_trim</primary>
+         </indexterm>
+         <literal><function>numeric_trim(<type>numeric</type>)</function></literal>
+        </entry>
+        <entry><type>numeric</type></entry>
+        <entry>remove trailing decimal zeroes after the decimal point</entry>
+        <entry><literal>numeric_trim(8.4100)</literal></entry>
+        <entry><literal>8.41</literal></entry>
+       </row>
+ 
+       <row>
+        <entry>
+         <indexterm>
           <primary>pi</primary>
          </indexterm>
          <literal><function>pi()</function></literal>
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
new file mode 100644
index fa93a8c..2f62dc2
*** a/src/backend/utils/adt/numeric.c
--- b/src/backend/utils/adt/numeric.c
*************** numeric_power(PG_FUNCTION_ARGS)
*** 2825,2830 ****
--- 2825,2907 ----
  	PG_RETURN_NUMERIC(res);
  }
  
+ /*
+  * numeric_trim() -
+  *
+  *	Remove trailing decimal zeroes after the decimal point
+  */
+ Datum
+ numeric_trim(PG_FUNCTION_ARGS)
+ {
+ 	Numeric		num = PG_GETARG_NUMERIC(0);
+ 	NumericVar	arg;
+ 	Numeric		res;
+ 	int dscale;
+ 	int ndigits;
+ 
+ 	if (NUMERIC_IS_NAN(num))
+ 		PG_RETURN_NUMERIC(make_result(&const_nan));
+ 
+ 	init_var_from_num(num, &arg);
+ 
+ 	ndigits = arg.ndigits;
+ 
+ 	/* for simplicity in the loop below, do full NBASE digits at a time */
+ 	dscale = ((arg.dscale + DEC_DIGITS - 1) / DEC_DIGITS) * DEC_DIGITS;
+ 
+ 	/* trim unstored significant trailing zeroes right away */
+ 	if (dscale > (ndigits - arg.weight - 1) * DEC_DIGITS)
+ 		dscale = (ndigits - arg.weight - 1) * DEC_DIGITS;
+ 
+ 	while (dscale > 0 && ndigits > 0)
+ 	{
+ 		NumericDigit dig = arg.digits[ndigits - 1];
+ 
+ #if DEC_DIGITS == 4
+ 		if ((dig % 10) != 0)
+ 			break;
+ 		if (--dscale == 0)
+ 			break;
+ 		if ((dig % 100) != 0)
+ 			break;
+ 		if (--dscale == 0)
+ 			break;
+ 		if ((dig % 1000) != 0)
+ 			break;
+ 		if (--dscale == 0)
+ 			break;
+ #elif DEC_DIGITS == 2
+ 		if ((dig % 10) != 0)
+ 			break;
+ 		if (--dscale == 0)
+ 			break;
+ #elif DEC_DIGITS == 1
+ 		/* nothing to do */
+ #else
+ #error unsupported NBASE
+ #endif
+ 		if (dig != 0)
+ 			break;
+ 		--dscale;
+ 		--ndigits;
+ 	}
+ 	arg.dscale = dscale;
+ 	arg.ndigits = ndigits;
+ 
+ 	/* If it's zero, normalize the sign and weight */
+ 	if (ndigits == 0)
+ 	{
+ 		arg.sign = NUMERIC_POS;
+ 		arg.weight = 0;
+ 		arg.dscale = 0;
+ 	}
+ 
+ 	res = make_result(&arg);
+ 	free_var(&arg);
+ 
+ 	PG_RETURN_NUMERIC(res);
+ }
+ 
  
  /* ----------------------------------------------------------------------
   *
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
new file mode 100644
index d8640db..c8240cd
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
*************** DESCR("exponentiation");
*** 2361,2366 ****
--- 2361,2368 ----
  DATA(insert OID = 2169 ( power					PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_	numeric_power _null_ _null_ _null_ ));
  DESCR("exponentiation");
  DATA(insert OID = 1739 ( numeric_power			PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_	numeric_power _null_ _null_ _null_ ));
+ DATA(insert OID = 8888 ( numeric_trim			PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 1700 "1700" _null_ _null_ _null_ _null_ _null_	numeric_trim _null_ _null_ _null_ ));
+ DESCR("remove trailing decimal zeroes after the decimal point");
  DATA(insert OID = 1740 ( numeric				PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 1700 "23" _null_ _null_ _null_ _null_ _null_ int4_numeric _null_ _null_ _null_ ));
  DESCR("convert int4 to numeric");
  DATA(insert OID = 1741 ( log					PGNSP PGUID 14 1 0 0 0 f f f f t f i s 1 0 1700 "1700" _null_ _null_ _null_ _null_ _null_ "select pg_catalog.log(10, $1)" _null_ _null_ _null_ ));
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
new file mode 100644
index e610bf3..ac0cb8b
*** a/src/include/utils/builtins.h
--- b/src/include/utils/builtins.h
*************** extern Datum numeric_exp(PG_FUNCTION_ARG
*** 1022,1027 ****
--- 1022,1028 ----
  extern Datum numeric_ln(PG_FUNCTION_ARGS);
  extern Datum numeric_log(PG_FUNCTION_ARGS);
  extern Datum numeric_power(PG_FUNCTION_ARGS);
+ extern Datum numeric_trim(PG_FUNCTION_ARGS);
  extern Datum int4_numeric(PG_FUNCTION_ARGS);
  extern Datum numeric_int4(PG_FUNCTION_ARGS);
  extern Datum int8_numeric(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/expected/numeric.out b/src/test/regress/expected/numeric.out
new file mode 100644
index caac424..e99cee0
*** a/src/test/regress/expected/numeric.out
--- b/src/test/regress/expected/numeric.out
*************** select log(3.1954752e47, 9.4792021e-73);
*** 1852,1854 ****
--- 1852,2013 ----
   -1.51613372350688302142917386143459361608600157692779164475351842333265418126982165
  (1 row)
  
+ --
+ -- Tests for numeric_trim()
+ --
+ select numeric_trim('NaN');
+  numeric_trim 
+ --------------
+           NaN
+ (1 row)
+ 
+ select numeric_trim('0');
+  numeric_trim 
+ --------------
+             0
+ (1 row)
+ 
+ select numeric_trim('0.0');
+  numeric_trim 
+ --------------
+             0
+ (1 row)
+ 
+ select numeric_trim('0.0000000000000000000000');
+  numeric_trim 
+ --------------
+             0
+ (1 row)
+ 
+ select numeric_trim('1.0');
+  numeric_trim 
+ --------------
+             1
+ (1 row)
+ 
+ select numeric_trim('1.00');
+  numeric_trim 
+ --------------
+             1
+ (1 row)
+ 
+ select numeric_trim('1.00000');
+  numeric_trim 
+ --------------
+             1
+ (1 row)
+ 
+ select numeric_trim('1.1');
+  numeric_trim 
+ --------------
+           1.1
+ (1 row)
+ 
+ select numeric_trim('1.11');
+  numeric_trim 
+ --------------
+          1.11
+ (1 row)
+ 
+ select numeric_trim('1.111');
+  numeric_trim 
+ --------------
+         1.111
+ (1 row)
+ 
+ select numeric_trim('1.1111');
+  numeric_trim 
+ --------------
+        1.1111
+ (1 row)
+ 
+ select numeric_trim('1.11111');
+  numeric_trim 
+ --------------
+       1.11111
+ (1 row)
+ 
+ select numeric_trim('1.010');
+  numeric_trim 
+ --------------
+          1.01
+ (1 row)
+ 
+ select numeric_trim('1.0010');
+  numeric_trim 
+ --------------
+         1.001
+ (1 row)
+ 
+ select numeric_trim('1.00010');
+  numeric_trim 
+ --------------
+        1.0001
+ (1 row)
+ 
+ select numeric_trim('1.000010');
+  numeric_trim 
+ --------------
+       1.00001
+ (1 row)
+ 
+ select numeric_trim('1.00001000000');
+  numeric_trim 
+ --------------
+       1.00001
+ (1 row)
+ 
+ select numeric_trim('1.001000000');
+  numeric_trim 
+ --------------
+         1.001
+ (1 row)
+ 
+ select numeric_trim('5124124800.10');
+  numeric_trim 
+ --------------
+  5124124800.1
+ (1 row)
+ 
+ select numeric_trim('5124124800.010');
+  numeric_trim  
+ ---------------
+  5124124800.01
+ (1 row)
+ 
+ select numeric_trim('5124124800.0010');
+   numeric_trim  
+ ----------------
+  5124124800.001
+ (1 row)
+ 
+ select numeric_trim('5124124800.00010');
+   numeric_trim   
+ -----------------
+  5124124800.0001
+ (1 row)
+ 
+ select numeric_trim('5124124800.000010');
+    numeric_trim   
+ ------------------
+  5124124800.00001
+ (1 row)
+ 
+ select numeric_trim('5124124800.0000010');
+    numeric_trim    
+ -------------------
+  5124124800.000001
+ (1 row)
+ 
+ select numeric_trim('5124124800.00000100000000000');
+    numeric_trim    
+ -------------------
+  5124124800.000001
+ (1 row)
+ 
+ select numeric_trim('5124124800.00100000000000');
+   numeric_trim  
+ ----------------
+  5124124800.001
+ (1 row)
+ 
diff --git a/src/test/regress/sql/numeric.sql b/src/test/regress/sql/numeric.sql
new file mode 100644
index 0a4d1cb..c545666
*** a/src/test/regress/sql/numeric.sql
--- b/src/test/regress/sql/numeric.sql
*************** select log(1.23e-89, 6.4689e45);
*** 983,985 ****
--- 983,1017 ----
  select log(0.99923, 4.58934e34);
  select log(1.000016, 8.452010e18);
  select log(3.1954752e47, 9.4792021e-73);
+ 
+ 
+ --
+ -- Tests for numeric_trim()
+ --
+ 
+ select numeric_trim('NaN');
+ select numeric_trim('0');
+ select numeric_trim('0.0');
+ select numeric_trim('0.0000000000000000000000');
+ select numeric_trim('1.0');
+ select numeric_trim('1.00');
+ select numeric_trim('1.00000');
+ select numeric_trim('1.1');
+ select numeric_trim('1.11');
+ select numeric_trim('1.111');
+ select numeric_trim('1.1111');
+ select numeric_trim('1.11111');
+ select numeric_trim('1.010');
+ select numeric_trim('1.0010');
+ select numeric_trim('1.00010');
+ select numeric_trim('1.000010');
+ select numeric_trim('1.00001000000');
+ select numeric_trim('1.001000000');
+ select numeric_trim('5124124800.10');
+ select numeric_trim('5124124800.010');
+ select numeric_trim('5124124800.0010');
+ select numeric_trim('5124124800.00010');
+ select numeric_trim('5124124800.000010');
+ select numeric_trim('5124124800.0000010');
+ select numeric_trim('5124124800.00000100000000000');
+ select numeric_trim('5124124800.00100000000000');
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to