diff --git a/Changes b/Changes
index 8bd8d4c19..69beabd23 100644
--- a/Changes
+++ b/Changes
@@ -5,6 +5,8 @@ indicates the contributor was also the author of the fix; Thanks!
 
 * Verilator 3.82***
 
+***  Support $ceil, $floor, etc.  [Alex Solomatnikov]
+
 **** Fix MSVC compile warning with trunc/round, bug394. [Amir Gonnen]
 
 
diff --git a/src/V3Ast.h b/src/V3Ast.h
index 08841d4e4..d07fe7835 100644
--- a/src/V3Ast.h
+++ b/src/V3Ast.h
@@ -27,6 +27,7 @@
 #include "V3Error.h"
 #include "V3Number.h"
 #include <vector>
+#include <cmath>
 
 #include "V3Ast__gen_classes.h"	// From ./astgen
 // Things like:
@@ -825,6 +826,7 @@ public:
     static int	instrCountPli() { return 20; }		///< Instruction cycles to call pli routines
     static int	instrCountDouble() { return 8; }	///< Instruction cycles to convert or do floats
     static int	instrCountDoubleDiv() { return 40; }	///< Instruction cycles to divide floats
+    static int	instrCountDoubleTrig() { return 200; }	///< Instruction cycles to do triganomics
     static int	instrCountCall() { return instrCountBranch()+10; }	///< Instruction cycles to call subroutine
     static int	instrCountTime() { return instrCountCall()+5; }		///< Instruction cycles to determine simulation time
 
diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h
index e9713bff4..cc36ea172 100644
--- a/src/V3AstNodes.h
+++ b/src/V3AstNodes.h
@@ -2832,6 +2832,90 @@ struct AstFGetC : public AstNodeUniop {
     AstNode*	filep() const { return lhsp(); }
 };
 
+struct AstCeilD : public AstNodeUniop {
+    AstCeilD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
+	numeric(AstNumeric::DOUBLE); }
+    ASTNODE_NODE_FUNCS(CeilD, CEILD)
+    virtual void numberOperate(V3Number& out, const V3Number& lhs) {
+	out.setDouble(ceil(lhs.toDouble())); }
+    virtual string emitVerilog() { return "%f$ceil(%l)"; }
+    virtual string emitC() { return "ceil(%li)"; }
+    virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
+    virtual bool sizeMattersLhs() {return false;}
+    virtual int instrCount()	const { return instrCountDoubleTrig(); }
+    virtual bool doubleFlavor() const { return true; }
+};
+
+struct AstExpD : public AstNodeUniop {
+    AstExpD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
+	numeric(AstNumeric::DOUBLE); }
+    ASTNODE_NODE_FUNCS(ExpD, EXPD)
+    virtual void numberOperate(V3Number& out, const V3Number& lhs) {
+	out.setDouble(exp(lhs.toDouble())); }
+    virtual string emitVerilog() { return "%f$exp(%l)"; }
+    virtual string emitC() { return "exp(%li)"; }
+    virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
+    virtual bool sizeMattersLhs() {return false;}
+    virtual int instrCount()	const { return instrCountDoubleTrig(); }
+    virtual bool doubleFlavor() const { return true; }
+};
+
+struct AstFloorD : public AstNodeUniop {
+    AstFloorD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
+	numeric(AstNumeric::DOUBLE); }
+    ASTNODE_NODE_FUNCS(FloorD, FLOORD)
+    virtual void numberOperate(V3Number& out, const V3Number& lhs) {
+	out.setDouble(floor(lhs.toDouble())); }
+    virtual string emitVerilog() { return "%f$floor(%l)"; }
+    virtual string emitC() { return "floor(%li)"; }
+    virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
+    virtual bool sizeMattersLhs() {return false;}
+    virtual int instrCount()	const { return instrCountDoubleTrig(); }
+    virtual bool doubleFlavor() const { return true; }
+};
+
+struct AstLogD : public AstNodeUniop {
+    AstLogD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
+	numeric(AstNumeric::DOUBLE); }
+    ASTNODE_NODE_FUNCS(LogD, LOGD)
+    virtual void numberOperate(V3Number& out, const V3Number& lhs) {
+	out.setDouble(log(lhs.toDouble())); }
+    virtual string emitVerilog() { return "%f$ln(%l)"; }
+    virtual string emitC() { return "log(%li)"; }
+    virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
+    virtual bool sizeMattersLhs() {return false;}
+    virtual int instrCount()	const { return instrCountDoubleTrig(); }
+    virtual bool doubleFlavor() const { return true; }
+};
+
+struct AstLog10D : public AstNodeUniop {
+    AstLog10D(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
+	numeric(AstNumeric::DOUBLE); }
+    ASTNODE_NODE_FUNCS(Log10D, LOG10D)
+    virtual void numberOperate(V3Number& out, const V3Number& lhs) {
+	out.setDouble(log10(lhs.toDouble())); }
+    virtual string emitVerilog() { return "%f$log10(%l)"; }
+    virtual string emitC() { return "log10(%li)"; }
+    virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
+    virtual bool sizeMattersLhs() {return false;}
+    virtual int instrCount()	const { return instrCountDoubleTrig(); }
+    virtual bool doubleFlavor() const { return true; }
+};
+
+struct AstSqrtD : public AstNodeUniop {
+    AstSqrtD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
+	numeric(AstNumeric::DOUBLE); }
+    ASTNODE_NODE_FUNCS(SqrtD, SQRTD)
+    virtual void numberOperate(V3Number& out, const V3Number& lhs) {
+	out.setDouble(sqrt(lhs.toDouble())); }
+    virtual string emitVerilog() { return "%f$sqrt(%l)"; }
+    virtual string emitC() { return "sqrt(%li)"; }
+    virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
+    virtual bool sizeMattersLhs() {return false;}
+    virtual int instrCount()	const { return instrCountDoubleTrig(); }
+    virtual bool doubleFlavor() const { return true; }
+};
+
 //======================================================================
 // Binary ops
 
diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp
index e7c9181dc..d04e16943 100644
--- a/src/V3EmitC.cpp
+++ b/src/V3EmitC.cpp
@@ -546,7 +546,7 @@ public:
 	    }
 	    ofp()->printf(",0x%08" VL_PRI64 "x)", (vluint64_t)(nodep->num().dataWord(0)));
 	} else if (nodep->isDouble()) {
-	    ofp()->printf("%g", nodep->num().toDouble());
+	    ofp()->printf("%.17g", nodep->num().toDouble());
 	} else if (nodep->isQuad()) {
 	    vluint64_t num = nodep->toUQuad();
 	    if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", num);
diff --git a/src/V3Number.cpp b/src/V3Number.cpp
index 653d2631a..67f7f5d97 100644
--- a/src/V3Number.cpp
+++ b/src/V3Number.cpp
@@ -25,6 +25,7 @@
 #include <cstdio>
 #include <cstdarg>
 #include <algorithm>
+#include <iomanip>
 #include "V3Number.h"
 
 #define MAX_SPRINTF_DOUBLE_SIZE 100  // Maximum characters with a sprintf %e/%f/%g (probably < 30)
@@ -337,6 +338,7 @@ string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
     ostringstream out;
 
     if (isDouble()) {
+	out.precision(17);
 	out<<toDouble();
 	return out.str();
     }
diff --git a/src/V3Width.cpp b/src/V3Width.cpp
index 53bd58bdb..8371d2051 100644
--- a/src/V3Width.cpp
+++ b/src/V3Width.cpp
@@ -208,6 +208,13 @@ private:
     virtual void visit(AstPowD* nodep, AstNUser* vup) {		visit_math_Or_LRr(nodep,vup); }
     // Signed/Real: Output real or signed iff LHS signed/real
     virtual void visit(AstNegateD* nodep, AstNUser* vup) {	visit_math_Or_Lr(nodep,vup); }
+    // Real: Output real
+    virtual void visit(AstCeilD* nodep, AstNUser* vup) {	visit_math_Or_Lr(nodep,vup); }
+    virtual void visit(AstExpD* nodep, AstNUser* vup) {		visit_math_Or_Lr(nodep,vup); }
+    virtual void visit(AstFloorD* nodep, AstNUser* vup) {	visit_math_Or_Lr(nodep,vup); }
+    virtual void visit(AstLogD* nodep, AstNUser* vup) {		visit_math_Or_Lr(nodep,vup); }
+    virtual void visit(AstLog10D* nodep, AstNUser* vup) {	visit_math_Or_Lr(nodep,vup); }
+    virtual void visit(AstSqrtD* nodep, AstNUser* vup) {	visit_math_Or_Lr(nodep,vup); }
  
     // Widths: out signed/unsigned width = lhs width, input un|signed 
     virtual void visit(AstSigned* nodep, AstNUser* vup) {	visit_Ous_Lus_Wforce(nodep,vup,AstNumeric::SIGNED); }
@@ -1188,14 +1195,14 @@ private:
 	nodep->taskp()->iterate(*this);
 	//
 	// And do the arguments to the task/function too
-	for (int accept_mode=1; accept_mode>=0; accept_mode--) {  // Avoid duplicate code; just do inner stuff twice
+	for (int accept_mode=0; accept_mode<3; accept_mode++) {  // Avoid duplicate code; just do inner stuff several times
+	  reloop:
 	    V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp());
-	    bool lastloop = false;
-	    for (V3TaskConnects::iterator it=tconnects.begin(); !lastloop && it!=tconnects.end(); ++it) {
+	    for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) {
 		AstVar* portp = it->first;
 		AstNode* pinp = it->second;
 		if (pinp!=NULL) {  // Else argument error we'll find later
-		    if (accept_mode) {
+		    if (accept_mode==0) {
 			// Prelim may cause the node to get replaced; we've lost our
 			// pointer, so need to iterate separately later
 			if (portp->attrSFormat()
@@ -1214,7 +1221,7 @@ private:
 			    }
 			    handle.relink(newp);
 			    // Connection list is now incorrect (has extra args in it).
-			    lastloop = true;  // so exit early; next loop will correct it
+			    goto reloop;  // so exit early; next loop will correct it
 			}
 			else if (portp->basicp() && portp->basicp()->keyword()==AstBasicDTypeKwd::STRING
 				 && !pinp->castCvtPackString()
@@ -1228,7 +1235,12 @@ private:
 			    pinp = newp;
 			}
 			pinp->accept(*this,WidthVP(portp->width(),portp->widthMin(),PRELIM).p());  pinp=NULL;
-		    } else {
+		    } else if (accept_mode==1) {
+			// Change data types based on above accept completion
+			if (portp->isDouble()) {
+			    spliceCvtD(pinp); pinp=NULL;
+			}
+		    } else if (accept_mode==2) {
 			// Do PRELIM again, because above accept may have exited early due to node replacement
 			pinp->accept(*this,WidthVP(portp->width(),portp->widthMin(),BOTH).p());
 			if ((portp->isOutput() || portp->isInout())
@@ -1585,20 +1597,18 @@ private:
     }
     void visit_math_Or_LRr(AstNodeBiop* nodep, AstNUser* vup) {
 	if (vup->c()->prelim()) {  // First stage evaluation
+	    nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
+	    nodep->rhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
 	    checkCvtD(nodep->lhsp());
 	    checkCvtD(nodep->rhsp());
 	    nodep->numeric(AstNumeric::DOUBLE);
-	    // Determine expression widths only relying on what's in the subops
-	    nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
-	    nodep->rhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
 	}
     }
     void visit_math_Or_Lr(AstNodeUniop* nodep, AstNUser* vup) {
 	if (vup->c()->prelim()) {  // First stage evaluation
+	    nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
 	    checkCvtD(nodep->lhsp());
 	    nodep->numeric(AstNumeric::DOUBLE);
-	    // Determine expression widths only relying on what's in the subops
-	    nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
 	}
     }
 
diff --git a/src/verilog.l b/src/verilog.l
index 0df0d81a5..37bafd47e 100644
--- a/src/verilog.l
+++ b/src/verilog.l
@@ -175,7 +175,9 @@ word	[a-zA-Z0-9_]+
   "$c"[0-9]*		{ FL; return yD_C; }		/*Verilator only*/
   /*     System Tasks */
   "$bitstoreal"		{ FL; return yD_BITSTOREAL; }
+  "$ceil"		{ FL; return yD_CEIL; }
   "$display"		{ FL; return yD_DISPLAY; }
+  "$exp"		{ FL; return yD_EXP; }
   "$fclose"		{ FL; return yD_FCLOSE; }
   "$fdisplay"		{ FL; return yD_FDISPLAY; }
   "$feof"		{ FL; return yD_FEOF; }
@@ -183,14 +185,18 @@ word	[a-zA-Z0-9_]+
   "$fgetc"		{ FL; return yD_FGETC; }
   "$fgets"		{ FL; return yD_FGETS; }
   "$finish"		{ FL; return yD_FINISH; }
+  "$floor"		{ FL; return yD_FLOOR; }
   "$fopen"		{ FL; return yD_FOPEN; }
   "$fscanf"		{ FL; return yD_FSCANF; }
   "$fullskew"		{ FL; return yaTIMINGSPEC; }
   "$fwrite"		{ FL; return yD_FWRITE; }
   "$hold"		{ FL; return yaTIMINGSPEC; }
   "$itor"		{ FL; return yD_ITOR; }
+  "$ln"			{ FL; return yD_LN; }
+  "$log10"		{ FL; return yD_LOG10; }
   "$nochange"		{ FL; return yaTIMINGSPEC; }
   "$period"		{ FL; return yaTIMINGSPEC; }
+  "$pow"		{ FL; return yD_POW; }
   "$random"		{ FL; return yD_RANDOM; }
   "$readmemb"		{ FL; return yD_READMEMB; }
   "$readmemh"		{ FL; return yD_READMEMH; }
@@ -204,6 +210,7 @@ word	[a-zA-Z0-9_]+
   "$setuphold"		{ FL; return yaTIMINGSPEC; }
   "$sformat"		{ FL; return yD_SFORMAT; }
   "$skew"		{ FL; return yaTIMINGSPEC; }
+  "$sqrt"		{ FL; return yD_SQRT; }
   "$sscanf"		{ FL; return yD_SSCANF; }
   "$stime"		{ FL; return yD_STIME; }
   "$stop"		{ FL; return yD_STOP; }
diff --git a/src/verilog.y b/src/verilog.y
index 9e176bc1c..f314b811e 100644
--- a/src/verilog.y
+++ b/src/verilog.y
@@ -386,10 +386,12 @@ class AstSenTree;
 %token<fl>		yD_BITS		"$bits"
 %token<fl>		yD_BITSTOREAL	"$bitstoreal"
 %token<fl>		yD_C		"$c"
+%token<fl>		yD_CEIL		"$ceil"
 %token<fl>		yD_CLOG2	"$clog2"
 %token<fl>		yD_COUNTONES	"$countones"
 %token<fl>		yD_DISPLAY	"$display"
 %token<fl>		yD_ERROR	"$error"
+%token<fl>		yD_EXP		"$exp"
 %token<fl>		yD_FATAL	"$fatal"
 %token<fl>		yD_FCLOSE	"$fclose"
 %token<fl>		yD_FDISPLAY	"$fdisplay"
@@ -398,14 +400,18 @@ class AstSenTree;
 %token<fl>		yD_FGETC	"$fgetc"
 %token<fl>		yD_FGETS	"$fgets"
 %token<fl>		yD_FINISH	"$finish"
+%token<fl>		yD_FLOOR	"$floor"
 %token<fl>		yD_FOPEN	"$fopen"
 %token<fl>		yD_FSCANF	"$fscanf"
 %token<fl>		yD_FWRITE	"$fwrite"
 %token<fl>		yD_INFO		"$info"
 %token<fl>		yD_ISUNKNOWN	"$isunknown"
 %token<fl>		yD_ITOR		"$itor"
+%token<fl>		yD_LN		"$ln"
+%token<fl>		yD_LOG10	"$log10"
 %token<fl>		yD_ONEHOT	"$onehot"
 %token<fl>		yD_ONEHOT0	"$onehot0"
+%token<fl>		yD_POW		"$pow"
 %token<fl>		yD_RANDOM	"$random"
 %token<fl>		yD_READMEMB	"$readmemb"
 %token<fl>		yD_READMEMH	"$readmemh"
@@ -414,6 +420,7 @@ class AstSenTree;
 %token<fl>		yD_RTOI		"$rtoi"
 %token<fl>		yD_SFORMAT	"$sformat"
 %token<fl>		yD_SIGNED	"$signed"
+%token<fl>		yD_SQRT		"$sqrt"
 %token<fl>		yD_SSCANF	"$sscanf"
 %token<fl>		yD_STIME	"$stime"
 %token<fl>		yD_STOP		"$stop"
@@ -2152,6 +2159,13 @@ system_f_call<nodep>:		// IEEE: system_tf_call (as func)
 	|	yaD_DPI parenE				{ $$ = new AstFuncRef($<fl>1,*$1,NULL); }
 	|	yaD_DPI '(' exprList ')'		{ $$ = new AstFuncRef($2,*$1,$3); }
 	//
+	|	yD_CEIL '(' expr ')'			{ $$ = new AstCeilD($1,$3); }
+	|	yD_EXP '(' expr ')'			{ $$ = new AstExpD($1,$3); }
+	|	yD_FLOOR '(' expr ')'			{ $$ = new AstFloorD($1,$3); }
+	|	yD_LN '(' expr ')'			{ $$ = new AstLogD($1,$3); }
+	|	yD_LOG10 '(' expr ')'			{ $$ = new AstLog10D($1,$3); }
+	|	yD_POW '(' expr ',' expr ')'		{ $$ = new AstPowD($1,$3,$5); }
+	|	yD_SQRT '(' expr ')'			{ $$ = new AstSqrtD($1,$3); }
 	|	yD_BITS '(' expr ')'			{ $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
 	|	yD_BITS '(' data_type ')'		{ $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
 	|	yD_BITSTOREAL '(' expr ')'		{ $$ = new AstBitsToRealD($1,$3); }
diff --git a/test_regress/t/t_func_bad.pl b/test_regress/t/t_func_bad.pl
index 866eb1b72..3444759bd 100755
--- a/test_regress/t/t_func_bad.pl
+++ b/test_regress/t/t_func_bad.pl
@@ -13,9 +13,11 @@ compile (
 	 expect=>
 q{%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add'
 %Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add'
+%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add'
 %Error: t/t_func_bad.v:\d+: Too many arguments in function call to FUNC 'add'
 %Error: t/t_func_bad.v:\d+: Too few arguments in function call to TASK 'x'
 %Error: t/t_func_bad.v:\d+: Too few arguments in function call to TASK 'x'
+%Error: t/t_func_bad.v:\d+: Too few arguments in function call to TASK 'x'
 %Error: Exiting due to},
 	 );
 
diff --git a/test_regress/t/t_math_trig.pl b/test_regress/t/t_math_trig.pl
new file mode 100755
index 000000000..7058e622f
--- /dev/null
+++ b/test_regress/t/t_math_trig.pl
@@ -0,0 +1,18 @@
+#!/usr/bin/perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2003 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+
+compile (
+	 );
+
+execute (
+	 check_finished=>1,
+     );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_math_trig.v b/test_regress/t/t_math_trig.v
new file mode 100644
index 000000000..3b2c549a6
--- /dev/null
+++ b/test_regress/t/t_math_trig.v
@@ -0,0 +1,155 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// Copyright 2011 by Wilson Snyder. This program is free software; you can
+// redistribute it and/or modify it under the terms of either the GNU
+// Lesser General Public License Version 3 or the Perl Artistic License
+// Version 2.0.
+
+module t (/*AUTOARG*/
+   // Inputs
+   clk
+   );
+   input clk;
+
+   real  r, r2;
+   integer 	cyc=0;
+
+   task check(integer line, real got, real ex);
+      if (got != ex) begin
+	 if ((got - ex) > 0.000001) begin
+	    $display("%%Error: Line %0d: Bad result, got=%0.99g expect=%0.99g",line,got,ex);
+	    $stop;
+	 end
+      end
+   endtask
+
+   initial begin
+      // Check constant propagation
+      check(`__LINE__, $ceil(-1.2),	-1);
+      check(`__LINE__, $ceil(1.2),	2);
+      check(`__LINE__, $exp(1.2),	3.3201169227365472380597566370852291584014892578125);
+      check(`__LINE__, $exp(0.0),	1);
+      check(`__LINE__, $exp(-1.2),	0.301194211912202136627314530414878390729427337646484375);
+      check(`__LINE__, $floor(-1.2),	-2);
+      check(`__LINE__, $floor(1.2),	1);
+      check(`__LINE__, $ln(1.2),	0.1823215567939545922460098381634452380239963531494140625);
+      //check(`__LINE__, $ln(0),	0);	// Bad value
+      //check(`__LINE__, $ln(-1.2),	0);	// Bad value
+      check(`__LINE__, $log10(1.2),	0.07918124604762481755226843915806966833770275115966796875);
+      //check(`__LINE__, $log10(0),	0);	// Bad value
+      //check(`__LINE__, $log10(-1.2),	0);
+      check(`__LINE__, $pow(2.3,1.2),	2.71689843249914897427288451581262052059173583984375);
+      check(`__LINE__, $pow(2.3,-1.2),	0.368066758785732861536388327294844202697277069091796875);
+      //check(`__LINE__, $pow(-2.3,1.2),0);	// Bad value
+      check(`__LINE__, $sqrt(1.2),	1.095445115010332148841598609578795731067657470703125);
+      //check(`__LINE__, $sqrt(-1.2),	0);	// Bad value
+`ifndef VERILATOR
+      check(`__LINE__, $acos (0.2),	1.369438406);	// Arg1 is -1..1
+      check(`__LINE__, $acosh(1.2),	0.622362503);
+      check(`__LINE__, $asin (0.2),	0.201357920);	// Arg1 is -1..1
+      check(`__LINE__, $asinh(1.2),	1.015973134);
+      check(`__LINE__, $atan (0.2),	0.197395559);
+      check(`__LINE__, $atan2(0.2,2.3),	0.086738338);	// Arg1 is -1..1
+      check(`__LINE__, $atanh(0.2),	0.202732554);	// Arg1 is -1..1
+      check(`__LINE__, $cos  (1.2),	0.362357754);
+      check(`__LINE__, $cosh (1.2),	1.810655567);
+      check(`__LINE__, $hypot(1.2,2.3),	2.594224354);
+      check(`__LINE__, $sin  (1.2),	0.932039085);
+      check(`__LINE__, $sinh (1.2),	1.509461355);
+      check(`__LINE__, $tan  (1.2),	2.572151622);
+      check(`__LINE__, $tanh (1.2),	0.833654607);
+`endif
+   end
+
+   real sum_ceil;
+   real sum_exp;
+   real sum_floor;
+   real sum_ln;
+   real sum_log10;
+   real sum_pow1;
+   real sum_pow2;
+   real sum_sqrt;
+
+   real sum_acos;
+   real sum_acosh;
+   real sum_asin;
+   real sum_asinh;
+   real sum_atan;
+   real sum_atan2;
+   real sum_atanh;
+   real sum_cos ;
+   real sum_cosh;
+   real sum_hypot;
+   real sum_sin;
+   real sum_sinh;
+   real sum_tan;
+   real sum_tanh;
+
+   // Test loop
+   always @ (posedge clk) begin
+      r = $itor(cyc)/10.0 - 5.0;  // Crosses 0
+`ifdef TEST_VERBOSE
+      $write("[%0t] cyc==%0d r=%g s_ln=%0.12g\n",$time, cyc, r, sum_ln);
+`endif
+      cyc <= cyc + 1;
+      if (cyc==0) begin
+      end
+      else if (cyc<90) begin
+	 // Setup
+	 sum_ceil	+= 1.0+$ceil(r);
+	 sum_exp	+= 1.0+$exp(r);
+	 sum_floor	+= 1.0+$floor(r);
+	 if (r > 0.0) sum_ln    += 1.0+$ln(r);
+	 if (r > 0.0) sum_log10 += 1.0+$log10(r);
+	 // Pow requires if arg1<0 then arg1 integral
+	 sum_pow1 += 1.0+$pow(2.3,r);
+	 if (r >= 0.0) sum_pow2 += 1.0+$pow(r,2.3);
+	 if (r >= 0.0) sum_sqrt += 1.0+$sqrt(r);
+
+`ifndef VERILATOR
+	 if (r>=-1.0 && r<=1.0) sum_acos  += 1.0+$acos (r);
+	 if (r>=1.0) sum_acosh += 1.0+$acosh(r);
+	 if (r>=-1.0 && r<=1.0) sum_asin  += 1.0+$asin (r);
+	 sum_asinh += 1.0+$asinh(r);
+	 sum_atan  += 1.0+$atan (r);
+	 if (r>=-1.0 && r<=1.0) sum_atan2 += 1.0+$atan2(r,2.3);
+	 if (r>=-1.0 && r<=1.0) sum_atanh += 1.0+$atanh(r);
+	 sum_cos   += 1.0+$cos  (r);
+	 sum_cosh  += 1.0+$cosh (r);
+	 sum_hypot += 1.0+$hypot(r,2.3);
+	 sum_sin   += 1.0+$sin  (r);
+	 sum_sinh  += 1.0+$sinh (r);
+	 sum_tan   += 1.0+$tan  (r);
+	 sum_tanh  += 1.0+$tanh (r);
+`endif
+      end
+      else if (cyc==99) begin
+	 check (`__LINE__, sum_ceil,	85);
+	 check (`__LINE__, sum_exp,	608.06652950);
+	 check (`__LINE__, sum_floor,	4);
+	 check (`__LINE__, sum_ln,	55.830941633);
+	 check (`__LINE__, sum_log10,	46.309585076);
+	 check (`__LINE__, sum_pow1,	410.98798177);
+	 check (`__LINE__, sum_pow2,	321.94765689);
+	 check (`__LINE__, sum_sqrt,	92.269677253);
+`ifndef VERILATOR
+	 check (`__LINE__, sum_acos,	53.986722862);
+	 check (`__LINE__, sum_acosh,	72.685208498);
+	 check (`__LINE__, sum_asin,	21);
+	 check (`__LINE__, sum_asinh,	67.034973416);
+	 check (`__LINE__, sum_atan,	75.511045389);
+	 check (`__LINE__, sum_atan2,	21);
+	 check (`__LINE__, sum_atanh,	0);
+	 check (`__LINE__, sum_cos,	72.042023124);
+	 check (`__LINE__, sum_cosh,	1054.0178222);
+	 check (`__LINE__, sum_hypot,	388.92858406);
+	 check (`__LINE__, sum_sin,	98.264184989);
+	 check (`__LINE__, sum_sinh,	0);
+	 check (`__LINE__, sum_tan,	1.7007946043);
+	 check (`__LINE__, sum_tanh,	79.003199681);
+`endif
+	 $write("*-* All Finished *-*\n");
+	 $finish;
+      end
+   end
+endmodule