diff --git a/doc/dynare.texi b/doc/dynare.texi
index 75cec054cd7ef4b86971c8b4b716f919ac6a3cce..703295a5de3cce19dbb04458fe7bfabb63ee4599 100644
--- a/doc/dynare.texi
+++ b/doc/dynare.texi
@@ -1244,6 +1244,14 @@ Base 10 logarithm.
 Square root.
 @end defun
 
+@defun abs (@var{x})
+Absolute value.
+@end defun
+
+@defun sign (@var{x})
+Signum function.
+@end defun
+
 @defun sin (@var{x})
 @defunx cos (@var{x})
 @defunx tan (@var{x})
diff --git a/preprocessor/CodeInterpreter.hh b/preprocessor/CodeInterpreter.hh
index 8d6e600ed0b34ef05750aae19a9a5e83a5fa8870..f730cbbc94ea013df5953d1b0a694de32ca17229 100644
--- a/preprocessor/CodeInterpreter.hh
+++ b/preprocessor/CodeInterpreter.hh
@@ -188,6 +188,8 @@ enum UnaryOpcode
     oAsinh,
     oAtanh,
     oSqrt,
+    oAbs,
+    oSign,
     oSteadyState,
     oSteadyStateParamDeriv, // for the derivative of the STEADY_STATE operator w.r.t. to a parameter
     oSteadyStateParam2ndDeriv, // for the 2nd derivative of the STEADY_STATE operator w.r.t. to a parameter
diff --git a/preprocessor/DataTree.cc b/preprocessor/DataTree.cc
index 267a97e60bf4ac266510ac120319cf1d49d49d12..24f97f981b5d2e691cac396d718e538a1a4356bb 100644
--- a/preprocessor/DataTree.cc
+++ b/preprocessor/DataTree.cc
@@ -401,6 +401,28 @@ DataTree::AddSqrt(expr_t iArg1)
     return Zero;
 }
 
+expr_t
+DataTree::AddAbs(expr_t iArg1)
+{
+  if (iArg1 == Zero)
+    return Zero;
+  if (iArg1 == One)
+    return One;
+  else
+    return AddUnaryOp(oAbs, iArg1);
+}
+
+expr_t
+DataTree::AddSign(expr_t iArg1)
+{
+  if (iArg1 == Zero)
+    return Zero;
+  if (iArg1 == One)
+    return One;
+  else
+    return AddUnaryOp(oSign, iArg1);
+}
+
 expr_t
 DataTree::AddErf(expr_t iArg1)
 {
diff --git a/preprocessor/DataTree.hh b/preprocessor/DataTree.hh
index 1456e9c86f617ae97b88ec0dde4794a3fee06944..0cb2ab7cd2c14347ca5aa728d2cd3a8dd7a093b7 100644
--- a/preprocessor/DataTree.hh
+++ b/preprocessor/DataTree.hh
@@ -176,6 +176,10 @@ public:
   expr_t AddAtanh(expr_t iArg1);
   //! Adds "sqrt(arg)" to model tree
   expr_t AddSqrt(expr_t iArg1);
+  //! Adds "abs(arg)" to model tree
+  expr_t AddAbs(expr_t iArg1);
+  //! Adds "sign(arg)" to model tree
+  expr_t AddSign(expr_t iArg1);
   //! Adds "erf(arg)" to model tree
   expr_t AddErf(expr_t iArg1);
   //! Adds "max(arg1,arg2)" to model tree
diff --git a/preprocessor/DynareBison.yy b/preprocessor/DynareBison.yy
index 09c45b7c35d2b6ae4fc29dd4dd5bafb5072362cf..bdd3f2de3b6153623b04eee47c8541497c3348e1 100644
--- a/preprocessor/DynareBison.yy
+++ b/preprocessor/DynareBison.yy
@@ -108,7 +108,7 @@ class ParsingDriver;
 %token LABELS LAPLACE LIK_ALGO LIK_INIT LINEAR LOAD_IDENT_FILES LOAD_MH_FILE LOAD_PARAMS_AND_STEADY_STATE LOGLINEAR
 %token MARKOWITZ MARGINAL_DENSITY MAX
 %token MFS MH_DROP MH_INIT_SCALE MH_JSCALE MH_MODE MH_NBLOCKS MH_REPLIC MH_RECOVER MIN MINIMAL_SOLVING_PERIODS
-%token MODE_CHECK MODE_COMPUTE MODE_FILE MODEL MODEL_COMPARISON MODEL_INFO MSHOCKS
+%token MODE_CHECK MODE_COMPUTE MODE_FILE MODEL MODEL_COMPARISON MODEL_INFO MSHOCKS ABS SIGN
 %token MODIFIEDHARMONICMEAN MOMENTS_VARENDO DIFFUSE_FILTER
 %token <string_val> NAME
 %token NAN_CONSTANT NO_STATIC NOBS NOCONSTANT NOCORR NODIAGNOSTIC NOFUNCTIONS
@@ -459,6 +459,10 @@ expression : '(' expression ')'
              { $$ = driver.add_atan($3); }
            | SQRT '(' expression ')'
              { $$ = driver.add_sqrt($3); }
+           | ABS '(' expression ')'
+             { $$ = driver.add_abs($3); }
+           | SIGN '(' expression ')'
+             { $$ = driver.add_sign($3); }
            | MAX '(' expression COMMA expression ')'
              { $$ = driver.add_max($3, $5); }
            | MIN '(' expression COMMA expression ')'
@@ -613,6 +617,10 @@ hand_side : '(' hand_side ')'
             { $$ = driver.add_atan($3); }
           | SQRT '(' hand_side ')'
             { $$ = driver.add_sqrt($3); }
+          | ABS '(' hand_side ')'
+            { $$ = driver.add_abs($3); }
+          | SIGN '(' hand_side ')'
+            { $$ = driver.add_sign($3); }
           | MAX '(' hand_side COMMA hand_side ')'
             { $$ = driver.add_max($3, $5); }
           | MIN '(' hand_side COMMA hand_side ')'
diff --git a/preprocessor/DynareFlex.ll b/preprocessor/DynareFlex.ll
index eec5336436c5b56e6193052eeb99f36f344dd4ca..6d8b51e4d5050639e1e9edac3e26774d10948623 100644
--- a/preprocessor/DynareFlex.ll
+++ b/preprocessor/DynareFlex.ll
@@ -511,6 +511,8 @@ string eofbuff;
 <DYNARE_STATEMENT,DYNARE_BLOCK>sqrt {return token::SQRT;}
 <DYNARE_STATEMENT,DYNARE_BLOCK>max {return token::MAX;}
 <DYNARE_STATEMENT,DYNARE_BLOCK>min {return token::MIN;}
+<DYNARE_STATEMENT,DYNARE_BLOCK>abs {return token::ABS;}
+<DYNARE_STATEMENT,DYNARE_BLOCK>sign {return token::SIGN;}
 <DYNARE_STATEMENT,DYNARE_BLOCK>normcdf {return token::NORMCDF;}
 <DYNARE_STATEMENT,DYNARE_BLOCK>normpdf {return token::NORMPDF;}
 <DYNARE_STATEMENT,DYNARE_BLOCK>erf {return token::ERF;}
diff --git a/preprocessor/ExprNode.cc b/preprocessor/ExprNode.cc
index 3974cbbfcb2486397f8314eca8a4dc45d5e8c088..386f28702632e09f7b7be4241ac8e89791305dd1 100644
--- a/preprocessor/ExprNode.cc
+++ b/preprocessor/ExprNode.cc
@@ -1323,6 +1323,11 @@ UnaryOpNode::composeDerivatives(expr_t darg, int deriv_id)
     case oSqrt:
       t11 = datatree.AddPlus(this, this);
       return datatree.AddDivide(darg, t11);
+    case oAbs:
+      t11 = datatree.AddSign(arg);
+      return datatree.AddTimes(t11, darg);
+    case oSign:
+      return datatree.Zero;
     case oSteadyState:
       if (datatree.isDynamic())
         {
@@ -1406,6 +1411,7 @@ UnaryOpNode::cost(const temporary_terms_t &temporary_terms, bool is_matlab) cons
     switch (op_code)
       {
       case oUminus:
+      case oSign:
         return cost + 70;
       case oExp:
         return cost + 160;
@@ -1437,6 +1443,7 @@ UnaryOpNode::cost(const temporary_terms_t &temporary_terms, bool is_matlab) cons
       case oAtanh:
         return cost + 350;
       case oSqrt:
+      case oAbs:
         return cost + 570;
       case oSteadyState:
       case oSteadyStateParamDeriv:
@@ -1449,6 +1456,7 @@ UnaryOpNode::cost(const temporary_terms_t &temporary_terms, bool is_matlab) cons
     switch (op_code)
       {
       case oUminus:
+      case oSign:
         return cost + 3;
       case oExp:
       case oAcosh:
@@ -1477,6 +1485,7 @@ UnaryOpNode::cost(const temporary_terms_t &temporary_terms, bool is_matlab) cons
       case oAtanh:
         return cost + 150;
       case oSqrt:
+      case oAbs:
         return cost + 90;
       case oSteadyState:
       case oSteadyStateParamDeriv:
@@ -1622,6 +1631,15 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
     case oSqrt:
       output << "sqrt";
       break;
+    case oAbs:
+      output << "abs";
+      break;
+    case oSign:
+      if (output_type == oCDynamicModel)
+        output << "copysign";
+      else
+        output << "sign";
+      break;
     case oSteadyState:
       ExprNodeOutputType new_output_type;
       switch (output_type)
@@ -1692,6 +1710,8 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
           && arg->precedence(output_type, temporary_terms) < precedence(output_type, temporary_terms)))
     {
       output << LEFT_PAR(output_type);
+      if (op_code == oSign && output_type == oCDynamicModel)
+        output << "1.0,";
       close_parenthesis = true;
     }
 
@@ -1763,6 +1783,10 @@ UnaryOpNode::eval_opcode(UnaryOpcode op_code, double v) throw (EvalException, Ev
       return (atanh(v));
     case oSqrt:
       return (sqrt(v));
+    case oAbs:
+      return (abs(v));
+    case oSign:
+      return (v > 0) ? 1 : ((v < 0) ? -1 : 0);
     case oSteadyState:
       return (v);
     case oSteadyStateParamDeriv:
@@ -1901,6 +1925,10 @@ UnaryOpNode::normalizeEquation(int var_endo, vector<pair<int, pair<expr_t, expr_
           return (make_pair(0, datatree.AddAtanh(New_expr_t)));
         case oSqrt:
           return (make_pair(0, datatree.AddSqrt(New_expr_t)));
+        case oAbs:
+          return (make_pair(0, datatree.AddAbs(New_expr_t)));
+        case oSign:
+          return (make_pair(0, datatree.AddSign(New_expr_t)));
         case oSteadyState:
           return (make_pair(0, datatree.AddSteadyState(New_expr_t)));
         case oErf:
@@ -1960,6 +1988,10 @@ UnaryOpNode::buildSimilarUnaryOpNode(expr_t alt_arg, DataTree &alt_datatree) con
       return alt_datatree.AddAtanh(alt_arg);
     case oSqrt:
       return alt_datatree.AddSqrt(alt_arg);
+    case oAbs:
+      return alt_datatree.AddAbs(alt_arg);
+    case oSign:
+      return alt_datatree.AddSign(alt_arg);
     case oSteadyState:
       return alt_datatree.AddSteadyState(alt_arg);
     case oSteadyStateParamDeriv:
diff --git a/preprocessor/ParsingDriver.cc b/preprocessor/ParsingDriver.cc
index 0e2d324a9a48853cfde0cb7e4a772f6abb34509d..0c138ca32b6866cc305e2dc3f65d92781c45a2af 100644
--- a/preprocessor/ParsingDriver.cc
+++ b/preprocessor/ParsingDriver.cc
@@ -1746,6 +1746,18 @@ ParsingDriver::add_sqrt(expr_t arg1)
   return data_tree->AddSqrt(arg1);
 }
 
+expr_t
+ParsingDriver::add_abs(expr_t arg1)
+{
+  return data_tree->AddAbs(arg1);
+}
+
+expr_t
+ParsingDriver::add_sign(expr_t arg1)
+{
+  return data_tree->AddSign(arg1);
+}
+
 expr_t
 ParsingDriver::add_max(expr_t arg1, expr_t arg2)
 {
diff --git a/preprocessor/ParsingDriver.hh b/preprocessor/ParsingDriver.hh
index c60a18c1fa529014de220f5da0ee50bd6087fc4e..74ddc41d046509f0abe9c87083780d5d413d8598 100644
--- a/preprocessor/ParsingDriver.hh
+++ b/preprocessor/ParsingDriver.hh
@@ -485,6 +485,10 @@ public:
   expr_t add_atanh(expr_t arg1);
   //! Writes token "sqrt(arg1)" to model tree
   expr_t add_sqrt(expr_t arg1);
+  //! Writes token "abs(arg1)" to model tree
+  expr_t add_abs(expr_t arg1);
+  //! Writes token "sign(arg1)" to model tree
+  expr_t add_sign(expr_t arg1);
   //! Writes token "max(arg1,arg2)" to model tree
   expr_t add_max(expr_t arg1, expr_t arg2);
   //! Writes token "min(arg1,arg2)" to model tree
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 3656805c0677b4faf8448175d405d32b23c98aab..6974b2998628556af0076551fc02ca2a13324d8e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -8,6 +8,7 @@ MODFILES = \
 	example1_use_dll.mod \
 	example1_with_tags.mod \
 	example1_irf_shocks.mod \
+	example1_abs_sign_dynamic.mod \
 	t_sgu_ex1.mod \
 	osr_example.mod \
 	optimal_policy/ramsey.mod \
diff --git a/tests/example1_abs_sign.mod b/tests/example1_abs_sign.mod
new file mode 100644
index 0000000000000000000000000000000000000000..6fea109aa355a4849ab2a26b85585e709897c984
--- /dev/null
+++ b/tests/example1_abs_sign.mod
@@ -0,0 +1,44 @@
+// Example 1 from Collard's guide to Dynare
+var y, c, k, a, h, b;
+varexo e, u;
+
+parameters beta, rho, alpha, delta, theta, psi, tau;
+
+alpha = 0.36;
+rho   = 0.95;
+tau   = 0.025;
+beta  = 0.99;
+delta = 0.025;
+psi   = 0;
+theta = 2.95;
+
+phi   = 0.1;
+
+model(use_dll);
+c*theta*h^(1+psi)=abs((1-alpha)*y);
+k = beta*(((exp(b)*c)/(exp(b(+1))*c(+1)))
+    *(exp(b(+1))*alpha*y(+1)+(1-delta)*k));
+y = exp(a)*(k(-1)^alpha)*(h^(1-alpha));
+k = exp(b)*(y-c)+(1-delta)*k(-1)*sign(k*k);
+a = rho*a(-1)+tau*b(-1) + e;
+b = tau*a(-1)+rho*b(-1) + u;
+end;
+
+initval;
+y = 1.08068253095672;
+c = 0.80359242014163;
+h = 0.29175631001732;
+k = 11.08360443260358;
+a = 0;
+b = 0;
+e = 0;
+u = 0;
+end;
+
+shocks;
+var e; stderr 0.009;
+var u; stderr 0.009;
+var e, u = phi*0.009*0.009;
+end;
+
+stoch_simul;