diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
new file mode 100644
index 2946122..434fb88
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -993,9 +993,9 @@
    Finally, <xref linkend="functions-math-trig-table"> shows the
    available trigonometric functions.  All trigonometric functions
    take arguments and return values of type <type>double
-   precision</type>. Trigonometric functions arguments are expressed
-   in radians. Inverse functions return values are expressed in
-   radians.  See unit transformation functions
+   precision</type>.  Each of the trigonometric functions comes in
+   two varieties, one which works in radians and one which works in
+   degrees.  See unit transformation functions
    <literal><function>radians()</function></literal> and
    <literal><function>degrees()</function></literal> above.
   </para>
@@ -1003,10 +1003,11 @@
    <table id="functions-math-trig-table">
     <title>Trigonometric Functions</title>
 
-    <tgroup cols="2">
+    <tgroup cols="3">
      <thead>
       <row>
-       <entry>Function</entry>
+       <entry>Function (radians)</entry>
+       <entry>Function (degrees)</entry>
        <entry>Description</entry>
       </row>
      </thead>
@@ -1018,6 +1019,11 @@
          <primary>acos</primary>
         </indexterm><literal><function>acos(<replaceable>x</replaceable>)</function></literal>
        </entry>
+       <entry>
+        <indexterm>
+         <primary>acosd</primary>
+        </indexterm><literal><function>acosd(<replaceable>x</replaceable>)</function></literal>
+       </entry>
        <entry>inverse cosine</entry>
       </row>
 
@@ -1028,6 +1034,12 @@
         </indexterm>
         <literal><function>asin(<replaceable>x</replaceable>)</function></literal>
        </entry>
+       <entry>
+        <indexterm>
+         <primary>asind</primary>
+        </indexterm>
+        <literal><function>asind(<replaceable>x</replaceable>)</function></literal>
+       </entry>
        <entry>inverse sine</entry>
       </row>
 
@@ -1038,6 +1050,12 @@
         </indexterm>
         <literal><function>atan(<replaceable>x</replaceable>)</function></literal>
        </entry>
+       <entry>
+        <indexterm>
+         <primary>atand</primary>
+        </indexterm>
+        <literal><function>atand(<replaceable>x</replaceable>)</function></literal>
+       </entry>
        <entry>inverse tangent</entry>
       </row>
 
@@ -1049,6 +1067,13 @@
         <literal><function>atan2(<replaceable>y</replaceable>,
         <replaceable>x</replaceable>)</function></literal>
        </entry>
+       <entry>
+        <indexterm>
+         <primary>atan2d</primary>
+        </indexterm>
+        <literal><function>atan2d(<replaceable>y</replaceable>,
+        <replaceable>x</replaceable>)</function></literal>
+       </entry>
        <entry>inverse tangent of
         <literal><replaceable>y</replaceable>/<replaceable>x</replaceable></literal></entry>
       </row>
@@ -1060,6 +1085,12 @@
         </indexterm>
         <literal><function>cos(<replaceable>x</replaceable>)</function></literal>
        </entry>
+       <entry>
+        <indexterm>
+         <primary>cosd</primary>
+        </indexterm>
+        <literal><function>cosd(<replaceable>x</replaceable>)</function></literal>
+       </entry>
        <entry>cosine</entry>
       </row>
 
@@ -1070,6 +1101,12 @@
         </indexterm>
         <literal><function>cot(<replaceable>x</replaceable>)</function></literal>
        </entry>
+       <entry>
+        <indexterm>
+         <primary>cotd</primary>
+        </indexterm>
+        <literal><function>cotd(<replaceable>x</replaceable>)</function></literal>
+       </entry>
        <entry>cotangent</entry>
       </row>
 
@@ -1080,6 +1117,12 @@
         </indexterm>
         <literal><function>sin(<replaceable>x</replaceable>)</function></literal>
        </entry>
+       <entry>
+        <indexterm>
+         <primary>sind</primary>
+        </indexterm>
+        <literal><function>sind(<replaceable>x</replaceable>)</function></literal>
+       </entry>
        <entry>sine</entry>
       </row>
 
@@ -1090,6 +1133,12 @@
         </indexterm>
         <literal><function>tan(<replaceable>x</replaceable>)</function></literal>
        </entry>
+       <entry>
+        <indexterm>
+         <primary>tand</primary>
+        </indexterm>
+        <literal><function>tand(<replaceable>x</replaceable>)</function></literal>
+       </entry>
        <entry>tangent</entry>
       </row>
      </tbody>
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
new file mode 100644
index 4e927d8..d2318f7
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -1535,7 +1535,7 @@ dacos(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 				 errmsg("input is out of range")));
 
-	CHECKFLOATVAL(result, isinf(arg1), true);
+	CHECKFLOATVAL(result, false, true);
 	PG_RETURN_FLOAT8(result);
 }
 
@@ -1556,7 +1556,7 @@ dasin(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 				 errmsg("input is out of range")));
 
-	CHECKFLOATVAL(result, isinf(arg1), true);
+	CHECKFLOATVAL(result, false, true);
 	PG_RETURN_FLOAT8(result);
 }
 
@@ -1577,7 +1577,7 @@ datan(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 				 errmsg("input is out of range")));
 
-	CHECKFLOATVAL(result, isinf(arg1), true);
+	CHECKFLOATVAL(result, false, true);
 	PG_RETURN_FLOAT8(result);
 }
 
@@ -1599,7 +1599,7 @@ datan2(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 				 errmsg("input is out of range")));
 
-	CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), true);
+	CHECKFLOATVAL(result, false, true);
 	PG_RETURN_FLOAT8(result);
 }
 
@@ -1620,7 +1620,7 @@ dcos(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 				 errmsg("input is out of range")));
 
-	CHECKFLOATVAL(result, isinf(arg1), true);
+	CHECKFLOATVAL(result, false, true);
 	PG_RETURN_FLOAT8(result);
 }
 
@@ -1642,7 +1642,7 @@ dcot(PG_FUNCTION_ARGS)
 				 errmsg("input is out of range")));
 
 	result = 1.0 / result;
-	CHECKFLOATVAL(result, true /* cotan(pi/2) == inf */ , true);
+	CHECKFLOATVAL(result, true /* cot(0) == Inf */ , true);
 	PG_RETURN_FLOAT8(result);
 }
 
@@ -1663,7 +1663,7 @@ dsin(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 				 errmsg("input is out of range")));
 
-	CHECKFLOATVAL(result, isinf(arg1), true);
+	CHECKFLOATVAL(result, false, true);
 	PG_RETURN_FLOAT8(result);
 }
 
@@ -1688,6 +1688,368 @@ dtan(PG_FUNCTION_ARGS)
 	PG_RETURN_FLOAT8(result);
 }
 
+
+/*
+ *		asind_q1		- returns the inverse sine of x in degrees, where x is
+ *						  assumed to be in the range [0, 1] and the result is
+ *						  an angle in the first quadrant (0 to 90 degrees).
+ *
+ * In this quadrant there are 3 special case inputs (0, 0.5 and 1) for which
+ * this function will return exact values (0, 30 and 90 respectively).
+ */
+static double
+asind_q1(double x)
+{
+	/*
+	 * Stitch together inverse sine and cosine functions for the ranges
+	 * [0, 0.5] and [0.5, 1].  Each expression below is guaranteed to return
+	 * exactly 30 for x=0.5, so the result is a continuous monotonic function
+	 * over the full range.
+	 */
+	if (x <= 0.5)
+		return (asin(x) / asin(0.5)) * 30;
+	else
+		return 90 - (acos(x) / acos(0.5)) * 60;
+}
+
+
+/*
+ *		acosd_q1		- returns the inverse cosine of x in degrees, where x
+ *						  is assumed to be in the range [0, 1] and the result
+ *						  is an angle in the first quadrant (0 to 90 degrees).
+ *
+ * In this quadrant there are 3 special case inputs (0, 0.5 and 1) for which
+ * this function will return exact values (0, 60 and 90 respectively).
+ */
+static double
+acosd_q1(double x)
+{
+	/*
+	 * Stitch together inverse sine and cosine functions for the ranges
+	 * [0, 0.5] and [0.5, 1].  Each expression below is guaranteed to return
+	 * exactly 60 for x=0.5, so the result is a continuous monotonic function
+	 * over the full range.
+	 */
+	if (x <= 0.5)
+		return 90 - (asin(x) / asin(0.5)) * 30;
+	else
+		return (acos(x) / acos(0.5)) * 60;
+}
+
+
+/*
+ *		dacosd			- returns the arccos of arg1 (degrees)
+ */
+Datum
+dacosd(PG_FUNCTION_ARGS)
+{
+	float8		arg1 = PG_GETARG_FLOAT8(0);
+	float8		result;
+
+	if (isinf(arg1) || arg1 < -1 || arg1 > 1)
+		ereport(ERROR,
+				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+				 errmsg("input is out of range")));
+
+	if (isnan(arg1))
+		result = arg1;
+	else if (arg1 >= 0)
+		result = acosd_q1(arg1);
+	else
+		result = 90 + asind_q1(-arg1);
+
+	CHECKFLOATVAL(result, false, true);
+	PG_RETURN_FLOAT8(result);
+}
+
+
+/*
+ *		dasind			- returns the arcsin of arg1 (degrees)
+ */
+Datum
+dasind(PG_FUNCTION_ARGS)
+{
+	float8		arg1 = PG_GETARG_FLOAT8(0);
+	float8		result;
+
+	if (isinf(arg1) || arg1 < -1 || arg1 > 1)
+		ereport(ERROR,
+				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+				 errmsg("input is out of range")));
+
+	if (isnan(arg1))
+		result = arg1;
+	else if (arg1 >= 0)
+		result = asind_q1(arg1);
+	else
+		result = -asind_q1(-arg1);
+
+	CHECKFLOATVAL(result, false, true);
+	PG_RETURN_FLOAT8(result);
+}
+
+
+/*
+ *		datand			- returns the arctan of arg1 (degrees)
+ */
+Datum
+datand(PG_FUNCTION_ARGS)
+{
+	float8		arg1 = PG_GETARG_FLOAT8(0);
+	float8		result;
+
+	errno = 0;
+	result = atan(arg1);
+	if (errno != 0)
+		ereport(ERROR,
+				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+				 errmsg("input is out of range")));
+
+	result = (result / atan(1.0)) * 45;
+	CHECKFLOATVAL(result, false, true);
+	PG_RETURN_FLOAT8(result);
+}
+
+
+/*
+ *		atan2d			- returns the arctan2 of arg1 (degrees)
+ */
+Datum
+datan2d(PG_FUNCTION_ARGS)
+{
+	float8		arg1 = PG_GETARG_FLOAT8(0);
+	float8		arg2 = PG_GETARG_FLOAT8(1);
+	float8		result;
+
+	errno = 0;
+	result = atan2(arg1, arg2);
+	if (errno != 0)
+		ereport(ERROR,
+				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+				 errmsg("input is out of range")));
+
+	result = (result / atan(1.0)) * 45;
+	CHECKFLOATVAL(result, false, true);
+	PG_RETURN_FLOAT8(result);
+}
+
+
+/*
+ *		sind_0_to_30	- returns the sine of an angle that lies between 0 and
+ *						  30 degrees.  This will return exactly 0 when x is 0,
+ *						  and exactly 0.5 when x is 30 degrees.
+ */
+static double
+sind_0_to_30(double x)
+{
+	return ( sin(x * (M_PI/180)) / sin(30 * (M_PI/180)) ) / 2;
+}
+
+
+/*
+ *		cosd_0_to_60	- returns the cosine of an angle that lies between 0
+ *						  and 60 degrees.  This will return exactly 1 when x
+ *						  is 0 and exactly 0.5 when x is 60 degrees.
+ */
+static double
+cosd_0_to_60(double x)
+{
+	return ( 2 - (1 - cos(x * (M_PI/180))) / (1 - cos(60 * (M_PI/180))) ) / 2;
+}
+
+
+/*
+ *		sind_q1			- returns the sine of an angle in the first quadrant
+ *						  (0 to 90 degrees).
+ */
+static double
+sind_q1(double x)
+{
+	/*
+	 * Stitch together the sine and cosine functions for the ranges [0, 30]
+	 * and [30, 90].  These guarantee to return exact answers at their
+	 * endpoints, so the overall result is a continuous monotonic function
+	 * that gives exact results when x = 0, 30 and 90 degrees.
+	 */
+	return x <= 30 ? sind_0_to_30(x) : cosd_0_to_60(90-x);
+}
+
+
+/*
+ *		cosd_q1			- returns the cosine of an angle in the first quadrant
+ *						  (0 to 90 degrees).
+ */
+static double
+cosd_q1(double x)
+{
+	/*
+	 * Stitch together the sine and cosine functions for the ranges [0, 60]
+	 * and [60, 90].  These guarantee to return exact answers at their
+	 * endpoints, so the overall result is a continuous monotonic function
+	 * that gives exact results when x = 0, 60 and 90 degrees.
+	 */
+	return x <= 60 ? cosd_0_to_60(x) : sind_0_to_30(90-x);
+}
+
+
+/*
+ *		dcosd			- returns the cosine of arg1 (degrees)
+ */
+Datum
+dcosd(PG_FUNCTION_ARGS)
+{
+	float8		arg1 = PG_GETARG_FLOAT8(0);
+	int			sign = 1;
+	float8		result;
+
+	/* Reduce the range of the input to [0,90] degrees */
+	arg1 = fmod(arg1, 360.0);
+	if (isnan(arg1))
+		PG_RETURN_FLOAT8(arg1);
+
+	if (arg1 < 0)
+		/* cosd(-x) = cosd(x) */
+		arg1 = -arg1;
+
+	if (arg1 > 180)
+		/* cosd(360-x) = cosd(x) */
+		arg1 = 360 - arg1;
+
+	if (arg1 > 90)
+	{
+		/* cosd(180-x) = -cosd(x) */
+		arg1 = 180 - arg1;
+		sign = -sign;
+	}
+
+	result = sign * cosd_q1(arg1);
+	CHECKFLOATVAL(result, false, true);
+	PG_RETURN_FLOAT8(result);
+}
+
+
+/*
+ *		dcotd			- returns the cotangent of arg1 (degrees)
+ */
+Datum
+dcotd(PG_FUNCTION_ARGS)
+{
+	float8		arg1 = PG_GETARG_FLOAT8(0);
+	int			sign = 1;
+	float8		result;
+
+	/* Reduce the range of the input to [0,90] degrees */
+	arg1 = fmod(arg1, 360.0);
+	if (isnan(arg1))
+		PG_RETURN_FLOAT8(arg1);
+
+	if (arg1 < 0)
+	{
+		/* cotd(-x) = -cotd(x) */
+		arg1 = -arg1;
+		sign = -sign;
+	}
+
+	if (arg1 > 180)
+	{
+		/* cotd(360-x) = -cotd(x) */
+		arg1 = 360 - arg1;
+		sign = -sign;
+	}
+
+	if (arg1 > 90)
+	{
+		/* cotd(180-x) = -cotd(x) */
+		arg1 = 180 - arg1;
+		sign = -sign;
+	}
+
+	result = sign * cosd_q1(arg1) / sind_q1(arg1);
+	CHECKFLOATVAL(result, true /* cotd(0) == Inf */ , true);
+	PG_RETURN_FLOAT8(result);
+}
+
+
+/*
+ *		dsind			- returns the sine of arg1 (degrees)
+ */
+Datum
+dsind(PG_FUNCTION_ARGS)
+{
+	float8		arg1 = PG_GETARG_FLOAT8(0);
+	int			sign = 1;
+	float8		result;
+
+	/* Reduce the range of the input to [0,90] degrees */
+	arg1 = fmod(arg1, 360.0);
+	if (isnan(arg1))
+		PG_RETURN_FLOAT8(arg1);
+
+	if (arg1 < 0)
+	{
+		/* sind(-x) = -sind(x) */
+		arg1 = -arg1;
+		sign = -sign;
+	}
+
+	if (arg1 > 180)
+	{
+		/* sind(360-x) = -sind(x) */
+		arg1 = 360 - arg1;
+		sign = -sign;
+	}
+
+	if (arg1 > 90)
+		/* sind(180-x) = sind(x) */
+		arg1 = 180 - arg1;
+
+	result = sign * sind_q1(arg1);
+	CHECKFLOATVAL(result, false, true);
+	PG_RETURN_FLOAT8(result);
+}
+
+
+/*
+ *		dtand			- returns the tangent of arg1 (degrees)
+ */
+Datum
+dtand(PG_FUNCTION_ARGS)
+{
+	float8		arg1 = PG_GETARG_FLOAT8(0);
+	int			sign = 1;
+	float8		result;
+
+	/* Reduce the range of the input to [0,90] degrees */
+	arg1 = fmod(arg1, 360.0);
+	if (isnan(arg1))
+		PG_RETURN_FLOAT8(arg1);
+
+	if (arg1 < 0)
+	{
+		/* tand(-x) = -tand(x) */
+		arg1 = -arg1;
+		sign = -sign;
+	}
+
+	if (arg1 > 180)
+	{
+		/* tand(360-x) = -tand(x) */
+        arg1 = 360 - arg1;
+		sign = -sign;
+	}
+
+	if (arg1 > 90)
+	{
+		/* tand(180-x) = -tand(x) */
+		arg1 = 180 - arg1;
+		sign = -sign;
+	}
+
+	result = sign * sind_q1(arg1) / cosd_q1(arg1);
+	CHECKFLOATVAL(result, true /* tand(90) == Inf */ , true);
+	PG_RETURN_FLOAT8(result);
+}
+
 
 /*
  *		degrees		- returns degrees converted from radians
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
new file mode 100644
index f688454..18a9e1d
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -1892,6 +1892,24 @@ DATA(insert OID = 1606 (  tan				PGNSP P
 DESCR("tangent");
 DATA(insert OID = 1607 (  cot				PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 701 "701" _null_ _null_ _null_ _null_ _null_ dcot _null_ _null_ _null_ ));
 DESCR("cotangent");
+
+DATA(insert OID = 3300 (  asind				PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 701 "701" _null_ _null_ _null_ _null_ _null_ dasind _null_ _null_ _null_ ));
+DESCR("arcsine, degrees");
+DATA(insert OID = 3308 (  acosd				PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 701 "701" _null_ _null_ _null_ _null_ _null_ dacosd _null_ _null_ _null_ ));
+DESCR("arccosine, degrees");
+DATA(insert OID = 3309 (  atand				PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 701 "701" _null_ _null_ _null_ _null_ _null_ datand _null_ _null_ _null_ ));
+DESCR("arctangent, degrees");
+DATA(insert OID = 3315 (  atan2d			PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ datan2d _null_ _null_ _null_ ));
+DESCR("arctangent, two arguments, degrees");
+DATA(insert OID = 3316 (  sind				PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 701 "701" _null_ _null_ _null_ _null_ _null_ dsind _null_ _null_ _null_ ));
+DESCR("sine, degrees");
+DATA(insert OID = 3317 (  cosd				PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 701 "701" _null_ _null_ _null_ _null_ _null_ dcosd _null_ _null_ _null_ ));
+DESCR("cosine, degrees");
+DATA(insert OID = 3318 (  tand				PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 701 "701" _null_ _null_ _null_ _null_ _null_ dtand _null_ _null_ _null_ ));
+DESCR("tangent, degrees");
+DATA(insert OID = 3319 (  cotd				PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 701 "701" _null_ _null_ _null_ _null_ _null_ dcotd _null_ _null_ _null_ ));
+DESCR("cotangent, degrees");
+
 DATA(insert OID = 1608 (  degrees			PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 701 "701" _null_ _null_ _null_ _null_ _null_ degrees _null_ _null_ _null_ ));
 DESCR("radians to degrees");
 DATA(insert OID = 1609 (  radians			PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 701 "701" _null_ _null_ _null_ _null_ _null_ radians _null_ _null_ _null_ ));
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
new file mode 100644
index fc1679e..62751ec
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -407,6 +407,14 @@ extern Datum dcos(PG_FUNCTION_ARGS);
 extern Datum dcot(PG_FUNCTION_ARGS);
 extern Datum dsin(PG_FUNCTION_ARGS);
 extern Datum dtan(PG_FUNCTION_ARGS);
+extern Datum dacosd(PG_FUNCTION_ARGS);
+extern Datum dasind(PG_FUNCTION_ARGS);
+extern Datum datand(PG_FUNCTION_ARGS);
+extern Datum datan2d(PG_FUNCTION_ARGS);
+extern Datum dcosd(PG_FUNCTION_ARGS);
+extern Datum dcotd(PG_FUNCTION_ARGS);
+extern Datum dsind(PG_FUNCTION_ARGS);
+extern Datum dtand(PG_FUNCTION_ARGS);
 extern Datum degrees(PG_FUNCTION_ARGS);
 extern Datum dpi(PG_FUNCTION_ARGS);
 extern Datum radians(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/expected/float8.out b/src/test/regress/expected/float8.out
new file mode 100644
index 6221538..a6261d2
--- a/src/test/regress/expected/float8.out
+++ b/src/test/regress/expected/float8.out
@@ -444,3 +444,330 @@ SELECT '' AS five, * FROM FLOAT8_TBL;
       | -1.2345678901234e-200
 (5 rows)
 
+-- Test the trigonometric functions.
+-- Use a lower precision to eliminate variations between platforms.
+SET extra_float_digits TO -5;
+-- sine and cosine
+SELECT x,
+       sin(radians(x)) AS sin_radians, sind(x),
+       cos(radians(x)) AS cos_radians, cosd(x)
+FROM generate_series(-360, 360, 10) AS t(x)
+WHERE x = 0 OR x % 90 != 0; -- skip tests that are very platform-dependent
+  x   |  sin_radians  |     sind      |  cos_radians  |     cosd      
+------+---------------+---------------+---------------+---------------
+ -350 |  0.1736481777 |  0.1736481777 |   0.984807753 |   0.984807753
+ -340 |  0.3420201433 |  0.3420201433 |  0.9396926208 |  0.9396926208
+ -330 |           0.5 |           0.5 |  0.8660254038 |  0.8660254038
+ -320 |  0.6427876097 |  0.6427876097 |  0.7660444431 |  0.7660444431
+ -310 |  0.7660444431 |  0.7660444431 |  0.6427876097 |  0.6427876097
+ -300 |  0.8660254038 |  0.8660254038 |           0.5 |           0.5
+ -290 |  0.9396926208 |  0.9396926208 |  0.3420201433 |  0.3420201433
+ -280 |   0.984807753 |   0.984807753 |  0.1736481777 |  0.1736481777
+ -260 |   0.984807753 |   0.984807753 | -0.1736481777 | -0.1736481777
+ -250 |  0.9396926208 |  0.9396926208 | -0.3420201433 | -0.3420201433
+ -240 |  0.8660254038 |  0.8660254038 |          -0.5 |          -0.5
+ -230 |  0.7660444431 |  0.7660444431 | -0.6427876097 | -0.6427876097
+ -220 |  0.6427876097 |  0.6427876097 | -0.7660444431 | -0.7660444431
+ -210 |           0.5 |           0.5 | -0.8660254038 | -0.8660254038
+ -200 |  0.3420201433 |  0.3420201433 | -0.9396926208 | -0.9396926208
+ -190 |  0.1736481777 |  0.1736481777 |  -0.984807753 |  -0.984807753
+ -170 | -0.1736481777 | -0.1736481777 |  -0.984807753 |  -0.984807753
+ -160 | -0.3420201433 | -0.3420201433 | -0.9396926208 | -0.9396926208
+ -150 |          -0.5 |          -0.5 | -0.8660254038 | -0.8660254038
+ -140 | -0.6427876097 | -0.6427876097 | -0.7660444431 | -0.7660444431
+ -130 | -0.7660444431 | -0.7660444431 | -0.6427876097 | -0.6427876097
+ -120 | -0.8660254038 | -0.8660254038 |          -0.5 |          -0.5
+ -110 | -0.9396926208 | -0.9396926208 | -0.3420201433 | -0.3420201433
+ -100 |  -0.984807753 |  -0.984807753 | -0.1736481777 | -0.1736481777
+  -80 |  -0.984807753 |  -0.984807753 |  0.1736481777 |  0.1736481777
+  -70 | -0.9396926208 | -0.9396926208 |  0.3420201433 |  0.3420201433
+  -60 | -0.8660254038 | -0.8660254038 |           0.5 |           0.5
+  -50 | -0.7660444431 | -0.7660444431 |  0.6427876097 |  0.6427876097
+  -40 | -0.6427876097 | -0.6427876097 |  0.7660444431 |  0.7660444431
+  -30 |          -0.5 |          -0.5 |  0.8660254038 |  0.8660254038
+  -20 | -0.3420201433 | -0.3420201433 |  0.9396926208 |  0.9396926208
+  -10 | -0.1736481777 | -0.1736481777 |   0.984807753 |   0.984807753
+    0 |             0 |             0 |             1 |             1
+   10 |  0.1736481777 |  0.1736481777 |   0.984807753 |   0.984807753
+   20 |  0.3420201433 |  0.3420201433 |  0.9396926208 |  0.9396926208
+   30 |           0.5 |           0.5 |  0.8660254038 |  0.8660254038
+   40 |  0.6427876097 |  0.6427876097 |  0.7660444431 |  0.7660444431
+   50 |  0.7660444431 |  0.7660444431 |  0.6427876097 |  0.6427876097
+   60 |  0.8660254038 |  0.8660254038 |           0.5 |           0.5
+   70 |  0.9396926208 |  0.9396926208 |  0.3420201433 |  0.3420201433
+   80 |   0.984807753 |   0.984807753 |  0.1736481777 |  0.1736481777
+  100 |   0.984807753 |   0.984807753 | -0.1736481777 | -0.1736481777
+  110 |  0.9396926208 |  0.9396926208 | -0.3420201433 | -0.3420201433
+  120 |  0.8660254038 |  0.8660254038 |          -0.5 |          -0.5
+  130 |  0.7660444431 |  0.7660444431 | -0.6427876097 | -0.6427876097
+  140 |  0.6427876097 |  0.6427876097 | -0.7660444431 | -0.7660444431
+  150 |           0.5 |           0.5 | -0.8660254038 | -0.8660254038
+  160 |  0.3420201433 |  0.3420201433 | -0.9396926208 | -0.9396926208
+  170 |  0.1736481777 |  0.1736481777 |  -0.984807753 |  -0.984807753
+  190 | -0.1736481777 | -0.1736481777 |  -0.984807753 |  -0.984807753
+  200 | -0.3420201433 | -0.3420201433 | -0.9396926208 | -0.9396926208
+  210 |          -0.5 |          -0.5 | -0.8660254038 | -0.8660254038
+  220 | -0.6427876097 | -0.6427876097 | -0.7660444431 | -0.7660444431
+  230 | -0.7660444431 | -0.7660444431 | -0.6427876097 | -0.6427876097
+  240 | -0.8660254038 | -0.8660254038 |          -0.5 |          -0.5
+  250 | -0.9396926208 | -0.9396926208 | -0.3420201433 | -0.3420201433
+  260 |  -0.984807753 |  -0.984807753 | -0.1736481777 | -0.1736481777
+  280 |  -0.984807753 |  -0.984807753 |  0.1736481777 |  0.1736481777
+  290 | -0.9396926208 | -0.9396926208 |  0.3420201433 |  0.3420201433
+  300 | -0.8660254038 | -0.8660254038 |           0.5 |           0.5
+  310 | -0.7660444431 | -0.7660444431 |  0.6427876097 |  0.6427876097
+  320 | -0.6427876097 | -0.6427876097 |  0.7660444431 |  0.7660444431
+  330 |          -0.5 |          -0.5 |  0.8660254038 |  0.8660254038
+  340 | -0.3420201433 | -0.3420201433 |  0.9396926208 |  0.9396926208
+  350 | -0.1736481777 | -0.1736481777 |   0.984807753 |   0.984807753
+(65 rows)
+
+-- test exactness
+SELECT x,
+       CASE WHEN sind(x) IN (-1,-0.5,0,0.5,1) THEN sind(x) END AS sind,
+       CASE WHEN cosd(x) IN (-1,-0.5,0,0.5,1) THEN cosd(x) END AS cosd
+FROM generate_series(0, 360, 30) AS t(x);
+  x  | sind | cosd 
+-----+------+------
+   0 |    0 |    1
+  30 |  0.5 |     
+  60 |      |  0.5
+  90 |    1 |    0
+ 120 |      | -0.5
+ 150 |  0.5 |     
+ 180 |    0 |   -1
+ 210 | -0.5 |     
+ 240 |      | -0.5
+ 270 |   -1 |    0
+ 300 |      |  0.5
+ 330 | -0.5 |     
+ 360 |    0 |    1
+(13 rows)
+
+-- tangent and cotangent
+SELECT x,
+       tan(radians(x)) AS tan_radians, tand(x),
+       cot(radians(x)) AS cot_radians, cotd(x)
+FROM generate_series(-360, 360, 10) AS t(x)
+WHERE x = 0 OR x % 90 != 0; -- skip tests that are very platform-dependent
+  x   |  tan_radians  |     tand      |  cot_radians  |     cotd      
+------+---------------+---------------+---------------+---------------
+ -350 |  0.1763269807 |  0.1763269807 |    5.67128182 |    5.67128182
+ -340 |  0.3639702343 |  0.3639702343 |   2.747477419 |   2.747477419
+ -330 |  0.5773502692 |  0.5773502692 |   1.732050808 |   1.732050808
+ -320 |  0.8390996312 |  0.8390996312 |   1.191753593 |   1.191753593
+ -310 |   1.191753593 |   1.191753593 |  0.8390996312 |  0.8390996312
+ -300 |   1.732050808 |   1.732050808 |  0.5773502692 |  0.5773502692
+ -290 |   2.747477419 |   2.747477419 |  0.3639702343 |  0.3639702343
+ -280 |    5.67128182 |    5.67128182 |  0.1763269807 |  0.1763269807
+ -260 |   -5.67128182 |   -5.67128182 | -0.1763269807 | -0.1763269807
+ -250 |  -2.747477419 |  -2.747477419 | -0.3639702343 | -0.3639702343
+ -240 |  -1.732050808 |  -1.732050808 | -0.5773502692 | -0.5773502692
+ -230 |  -1.191753593 |  -1.191753593 | -0.8390996312 | -0.8390996312
+ -220 | -0.8390996312 | -0.8390996312 |  -1.191753593 |  -1.191753593
+ -210 | -0.5773502692 | -0.5773502692 |  -1.732050808 |  -1.732050808
+ -200 | -0.3639702343 | -0.3639702343 |  -2.747477419 |  -2.747477419
+ -190 | -0.1763269807 | -0.1763269807 |   -5.67128182 |   -5.67128182
+ -170 |  0.1763269807 |  0.1763269807 |    5.67128182 |    5.67128182
+ -160 |  0.3639702343 |  0.3639702343 |   2.747477419 |   2.747477419
+ -150 |  0.5773502692 |  0.5773502692 |   1.732050808 |   1.732050808
+ -140 |  0.8390996312 |  0.8390996312 |   1.191753593 |   1.191753593
+ -130 |   1.191753593 |   1.191753593 |  0.8390996312 |  0.8390996312
+ -120 |   1.732050808 |   1.732050808 |  0.5773502692 |  0.5773502692
+ -110 |   2.747477419 |   2.747477419 |  0.3639702343 |  0.3639702343
+ -100 |    5.67128182 |    5.67128182 |  0.1763269807 |  0.1763269807
+  -80 |   -5.67128182 |   -5.67128182 | -0.1763269807 | -0.1763269807
+  -70 |  -2.747477419 |  -2.747477419 | -0.3639702343 | -0.3639702343
+  -60 |  -1.732050808 |  -1.732050808 | -0.5773502692 | -0.5773502692
+  -50 |  -1.191753593 |  -1.191753593 | -0.8390996312 | -0.8390996312
+  -40 | -0.8390996312 | -0.8390996312 |  -1.191753593 |  -1.191753593
+  -30 | -0.5773502692 | -0.5773502692 |  -1.732050808 |  -1.732050808
+  -20 | -0.3639702343 | -0.3639702343 |  -2.747477419 |  -2.747477419
+  -10 | -0.1763269807 | -0.1763269807 |   -5.67128182 |   -5.67128182
+    0 |             0 |             0 |      Infinity |      Infinity
+   10 |  0.1763269807 |  0.1763269807 |    5.67128182 |    5.67128182
+   20 |  0.3639702343 |  0.3639702343 |   2.747477419 |   2.747477419
+   30 |  0.5773502692 |  0.5773502692 |   1.732050808 |   1.732050808
+   40 |  0.8390996312 |  0.8390996312 |   1.191753593 |   1.191753593
+   50 |   1.191753593 |   1.191753593 |  0.8390996312 |  0.8390996312
+   60 |   1.732050808 |   1.732050808 |  0.5773502692 |  0.5773502692
+   70 |   2.747477419 |   2.747477419 |  0.3639702343 |  0.3639702343
+   80 |    5.67128182 |    5.67128182 |  0.1763269807 |  0.1763269807
+  100 |   -5.67128182 |   -5.67128182 | -0.1763269807 | -0.1763269807
+  110 |  -2.747477419 |  -2.747477419 | -0.3639702343 | -0.3639702343
+  120 |  -1.732050808 |  -1.732050808 | -0.5773502692 | -0.5773502692
+  130 |  -1.191753593 |  -1.191753593 | -0.8390996312 | -0.8390996312
+  140 | -0.8390996312 | -0.8390996312 |  -1.191753593 |  -1.191753593
+  150 | -0.5773502692 | -0.5773502692 |  -1.732050808 |  -1.732050808
+  160 | -0.3639702343 | -0.3639702343 |  -2.747477419 |  -2.747477419
+  170 | -0.1763269807 | -0.1763269807 |   -5.67128182 |   -5.67128182
+  190 |  0.1763269807 |  0.1763269807 |    5.67128182 |    5.67128182
+  200 |  0.3639702343 |  0.3639702343 |   2.747477419 |   2.747477419
+  210 |  0.5773502692 |  0.5773502692 |   1.732050808 |   1.732050808
+  220 |  0.8390996312 |  0.8390996312 |   1.191753593 |   1.191753593
+  230 |   1.191753593 |   1.191753593 |  0.8390996312 |  0.8390996312
+  240 |   1.732050808 |   1.732050808 |  0.5773502692 |  0.5773502692
+  250 |   2.747477419 |   2.747477419 |  0.3639702343 |  0.3639702343
+  260 |    5.67128182 |    5.67128182 |  0.1763269807 |  0.1763269807
+  280 |   -5.67128182 |   -5.67128182 | -0.1763269807 | -0.1763269807
+  290 |  -2.747477419 |  -2.747477419 | -0.3639702343 | -0.3639702343
+  300 |  -1.732050808 |  -1.732050808 | -0.5773502692 | -0.5773502692
+  310 |  -1.191753593 |  -1.191753593 | -0.8390996312 | -0.8390996312
+  320 | -0.8390996312 | -0.8390996312 |  -1.191753593 |  -1.191753593
+  330 | -0.5773502692 | -0.5773502692 |  -1.732050808 |  -1.732050808
+  340 | -0.3639702343 | -0.3639702343 |  -2.747477419 |  -2.747477419
+  350 | -0.1763269807 | -0.1763269807 |   -5.67128182 |   -5.67128182
+(65 rows)
+
+-- test exactness
+SELECT x,
+       CASE WHEN tand(x) IN (-1,0,1) THEN tand(x) END AS tand,
+       CASE WHEN cotd(x) IN (-1,0,1) THEN cotd(x) END AS cotd
+FROM generate_series(0, 360, 45) AS t(x);
+  x  | tand | cotd 
+-----+------+------
+   0 |    0 |     
+  45 |    1 |    1
+  90 |      |    0
+ 135 |   -1 |   -1
+ 180 |   -0 |     
+ 225 |    1 |    1
+ 270 |      |   -0
+ 315 |   -1 |   -1
+ 360 |    0 |     
+(9 rows)
+
+-- arcsine and arccosine
+SELECT x,
+       degrees(asin(x)) AS degrees_asin, asind(x),
+       degrees(acos(x)) AS degrees_acos, acosd(x)
+FROM generate_series(-1.0, 1.0, 0.1) AS t(x);
+  x   | degrees_asin |    asind     | degrees_acos |    acosd    
+------+--------------+--------------+--------------+-------------
+ -1.0 |          -90 |          -90 |          180 |         180
+ -0.9 | -64.15806724 | -64.15806724 |  154.1580672 | 154.1580672
+ -0.8 | -53.13010235 | -53.13010235 |  143.1301024 | 143.1301024
+ -0.7 |   -44.427004 |   -44.427004 |   134.427004 |  134.427004
+ -0.6 | -36.86989765 | -36.86989765 |  126.8698976 | 126.8698976
+ -0.5 |          -30 |          -30 |          120 |         120
+ -0.4 | -23.57817848 | -23.57817848 |  113.5781785 | 113.5781785
+ -0.3 | -17.45760312 | -17.45760312 |  107.4576031 | 107.4576031
+ -0.2 | -11.53695903 | -11.53695903 |   101.536959 |  101.536959
+ -0.1 | -5.739170477 | -5.739170477 |  95.73917048 | 95.73917048
+  0.0 |            0 |            0 |           90 |          90
+  0.1 |  5.739170477 |  5.739170477 |  84.26082952 | 84.26082952
+  0.2 |  11.53695903 |  11.53695903 |  78.46304097 | 78.46304097
+  0.3 |  17.45760312 |  17.45760312 |  72.54239688 | 72.54239688
+  0.4 |  23.57817848 |  23.57817848 |  66.42182152 | 66.42182152
+  0.5 |           30 |           30 |           60 |          60
+  0.6 |  36.86989765 |  36.86989765 |  53.13010235 | 53.13010235
+  0.7 |    44.427004 |    44.427004 |    45.572996 |   45.572996
+  0.8 |  53.13010235 |  53.13010235 |  36.86989765 | 36.86989765
+  0.9 |  64.15806724 |  64.15806724 |  25.84193276 | 25.84193276
+  1.0 |           90 |           90 |            0 |           0
+(21 rows)
+
+-- arctangent
+SELECT x, degrees(atan(x)) AS degrees_atan, atand(x)
+FROM (SELECT '-Infinity'::float8
+      UNION ALL
+      SELECT generate_series(-10, -2)
+      UNION ALL
+      SELECT generate_series(-1.0, 1.0, 0.1)
+      UNION ALL
+      SELECT generate_series(2, 10)
+      UNION ALL
+      SELECT 'Infinity'::float8
+      UNION ALL
+      SELECT 'NaN'::float8) AS t(x);
+     x     | degrees_atan |    atand     
+-----------+--------------+--------------
+ -Infinity |          -90 |          -90
+       -10 | -84.28940686 | -84.28940686
+        -9 | -83.65980825 | -83.65980825
+        -8 | -82.87498365 | -82.87498365
+        -7 | -81.86989765 | -81.86989765
+        -6 | -80.53767779 | -80.53767779
+        -5 | -78.69006753 | -78.69006753
+        -4 | -75.96375653 | -75.96375653
+        -3 | -71.56505118 | -71.56505118
+        -2 | -63.43494882 | -63.43494882
+        -1 |          -45 |          -45
+      -0.9 |  -41.9872125 |  -41.9872125
+      -0.8 | -38.65980825 | -38.65980825
+      -0.7 |  -34.9920202 |  -34.9920202
+      -0.6 | -30.96375653 | -30.96375653
+      -0.5 | -26.56505118 | -26.56505118
+      -0.4 | -21.80140949 | -21.80140949
+      -0.3 | -16.69924423 | -16.69924423
+      -0.2 | -11.30993247 | -11.30993247
+      -0.1 | -5.710593137 | -5.710593137
+         0 |            0 |            0
+       0.1 |  5.710593137 |  5.710593137
+       0.2 |  11.30993247 |  11.30993247
+       0.3 |  16.69924423 |  16.69924423
+       0.4 |  21.80140949 |  21.80140949
+       0.5 |  26.56505118 |  26.56505118
+       0.6 |  30.96375653 |  30.96375653
+       0.7 |   34.9920202 |   34.9920202
+       0.8 |  38.65980825 |  38.65980825
+       0.9 |   41.9872125 |   41.9872125
+         1 |           45 |           45
+         2 |  63.43494882 |  63.43494882
+         3 |  71.56505118 |  71.56505118
+         4 |  75.96375653 |  75.96375653
+         5 |  78.69006753 |  78.69006753
+         6 |  80.53767779 |  80.53767779
+         7 |  81.86989765 |  81.86989765
+         8 |  82.87498365 |  82.87498365
+         9 |  83.65980825 |  83.65980825
+        10 |  84.28940686 |  84.28940686
+  Infinity |           90 |           90
+       NaN |          NaN |          NaN
+(42 rows)
+
+-- 4 quadrant arctangent
+SELECT x, y, degrees(atan2(y, x)) AS degrees_atan2, atan2d(y, x)
+FROM (SELECT 10*cosd(a), 10*sind(a)
+      FROM generate_series(0, 360, 10) AS t(a)) AS t(x,y);
+      x       |      y       | degrees_atan2 | atan2d 
+--------------+--------------+---------------+--------
+           10 |            0 |             0 |      0
+   9.84807753 |  1.736481777 |            10 |     10
+  9.396926208 |  3.420201433 |            20 |     20
+  8.660254038 |            5 |            30 |     30
+  7.660444431 |  6.427876097 |            40 |     40
+  6.427876097 |  7.660444431 |            50 |     50
+            5 |  8.660254038 |            60 |     60
+  3.420201433 |  9.396926208 |            70 |     70
+  1.736481777 |   9.84807753 |            80 |     80
+            0 |           10 |            90 |     90
+ -1.736481777 |   9.84807753 |           100 |    100
+ -3.420201433 |  9.396926208 |           110 |    110
+           -5 |  8.660254038 |           120 |    120
+ -6.427876097 |  7.660444431 |           130 |    130
+ -7.660444431 |  6.427876097 |           140 |    140
+ -8.660254038 |            5 |           150 |    150
+ -9.396926208 |  3.420201433 |           160 |    160
+  -9.84807753 |  1.736481777 |           170 |    170
+          -10 |            0 |           180 |    180
+  -9.84807753 | -1.736481777 |          -170 |   -170
+ -9.396926208 | -3.420201433 |          -160 |   -160
+ -8.660254038 |           -5 |          -150 |   -150
+ -7.660444431 | -6.427876097 |          -140 |   -140
+ -6.427876097 | -7.660444431 |          -130 |   -130
+           -5 | -8.660254038 |          -120 |   -120
+ -3.420201433 | -9.396926208 |          -110 |   -110
+ -1.736481777 |  -9.84807753 |          -100 |   -100
+            0 |          -10 |           -90 |    -90
+  1.736481777 |  -9.84807753 |           -80 |    -80
+  3.420201433 | -9.396926208 |           -70 |    -70
+            5 | -8.660254038 |           -60 |    -60
+  6.427876097 | -7.660444431 |           -50 |    -50
+  7.660444431 | -6.427876097 |           -40 |    -40
+  8.660254038 |           -5 |           -30 |    -30
+  9.396926208 | -3.420201433 |           -20 |    -20
+   9.84807753 | -1.736481777 |           -10 |    -10
+           10 |            0 |             0 |      0
+(37 rows)
+
diff --git a/src/test/regress/sql/float8.sql b/src/test/regress/sql/float8.sql
new file mode 100644
index 92a574a..49363d0
--- a/src/test/regress/sql/float8.sql
+++ b/src/test/regress/sql/float8.sql
@@ -167,3 +167,58 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('-1.2
 INSERT INTO FLOAT8_TBL(f1) VALUES ('-1.2345678901234e-200');
 
 SELECT '' AS five, * FROM FLOAT8_TBL;
+
+-- Test the trigonometric functions.
+-- Use a lower precision to eliminate variations between platforms.
+SET extra_float_digits TO -5;
+
+-- sine and cosine
+SELECT x,
+       sin(radians(x)) AS sin_radians, sind(x),
+       cos(radians(x)) AS cos_radians, cosd(x)
+FROM generate_series(-360, 360, 10) AS t(x)
+WHERE x = 0 OR x % 90 != 0; -- skip tests that are very platform-dependent
+
+-- test exactness
+SELECT x,
+       CASE WHEN sind(x) IN (-1,-0.5,0,0.5,1) THEN sind(x) END AS sind,
+       CASE WHEN cosd(x) IN (-1,-0.5,0,0.5,1) THEN cosd(x) END AS cosd
+FROM generate_series(0, 360, 30) AS t(x);
+
+-- tangent and cotangent
+SELECT x,
+       tan(radians(x)) AS tan_radians, tand(x),
+       cot(radians(x)) AS cot_radians, cotd(x)
+FROM generate_series(-360, 360, 10) AS t(x)
+WHERE x = 0 OR x % 90 != 0; -- skip tests that are very platform-dependent
+
+-- test exactness
+SELECT x,
+       CASE WHEN tand(x) IN (-1,0,1) THEN tand(x) END AS tand,
+       CASE WHEN cotd(x) IN (-1,0,1) THEN cotd(x) END AS cotd
+FROM generate_series(0, 360, 45) AS t(x);
+
+-- arcsine and arccosine
+SELECT x,
+       degrees(asin(x)) AS degrees_asin, asind(x),
+       degrees(acos(x)) AS degrees_acos, acosd(x)
+FROM generate_series(-1.0, 1.0, 0.1) AS t(x);
+
+-- arctangent
+SELECT x, degrees(atan(x)) AS degrees_atan, atand(x)
+FROM (SELECT '-Infinity'::float8
+      UNION ALL
+      SELECT generate_series(-10, -2)
+      UNION ALL
+      SELECT generate_series(-1.0, 1.0, 0.1)
+      UNION ALL
+      SELECT generate_series(2, 10)
+      UNION ALL
+      SELECT 'Infinity'::float8
+      UNION ALL
+      SELECT 'NaN'::float8) AS t(x);
+
+-- 4 quadrant arctangent
+SELECT x, y, degrees(atan2(y, x)) AS degrees_atan2, atan2d(y, x)
+FROM (SELECT 10*cosd(a), 10*sind(a)
+      FROM generate_series(0, 360, 10) AS t(a)) AS t(x,y);
