virtualize ErrorRateModel
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Tue, 06 Jan 2009 13:12:28 +0100
changeset 4038 c6f634d0fc6f
parent 4037 a8f42518c058
child 4039 50a070c2750c
virtualize ErrorRateModel
bindings/python/ns3_module_core.py
bindings/python/ns3_module_wifi.py
src/devices/wifi/error-rate-model.cc
src/devices/wifi/error-rate-model.h
src/devices/wifi/wifi-phy-test.cc
src/devices/wifi/wifi-test.cc
src/devices/wifi/wscript
src/devices/wifi/yans-error-rate-model.cc
src/devices/wifi/yans-error-rate-model.h
src/helper/yans-wifi-helper.cc
--- a/bindings/python/ns3_module_core.py	Tue Dec 30 21:51:36 2008 -0800
+++ b/bindings/python/ns3_module_core.py	Tue Jan 06 13:12:28 2009 +0100
@@ -1906,7 +1906,7 @@
     cls.add_method('ConnectWithoutContext', 
                    'void', 
                    [param('ns3::CallbackBase const &', 'cb')])
-    ## traced-value.h: void ns3::TracedValue<unsigned int>::Connect(ns3::CallbackBase const & cb, std::basic_string<char,std::char_traits<char>,std::allocator<char> > path) [member function]
+    ## traced-value.h: void ns3::TracedValue<unsigned int>::Connect(ns3::CallbackBase const & cb, std::string path) [member function]
     cls.add_method('Connect', 
                    'void', 
                    [param('ns3::CallbackBase const &', 'cb'), param('std::string', 'path')])
@@ -1914,7 +1914,7 @@
     cls.add_method('DisconnectWithoutContext', 
                    'void', 
                    [param('ns3::CallbackBase const &', 'cb')])
-    ## traced-value.h: void ns3::TracedValue<unsigned int>::Disconnect(ns3::CallbackBase const & cb, std::basic_string<char,std::char_traits<char>,std::allocator<char> > path) [member function]
+    ## traced-value.h: void ns3::TracedValue<unsigned int>::Disconnect(ns3::CallbackBase const & cb, std::string path) [member function]
     cls.add_method('Disconnect', 
                    'void', 
                    [param('ns3::CallbackBase const &', 'cb'), param('std::string', 'path')])
@@ -2062,7 +2062,7 @@
     module.add_function('TypeNameGet', 
                         'std::string', 
                         [], 
-                        template_parameters=['long'])
+                        template_parameters=['long long'])
     ## type-name.h: extern std::string ns3::TypeNameGet() [free function]
     module.add_function('TypeNameGet', 
                         'std::string', 
@@ -2082,7 +2082,7 @@
     module.add_function('TypeNameGet', 
                         'std::string', 
                         [], 
-                        template_parameters=['unsigned long'])
+                        template_parameters=['unsigned long long'])
     ## type-name.h: extern std::string ns3::TypeNameGet() [free function]
     module.add_function('TypeNameGet', 
                         'std::string', 
--- a/bindings/python/ns3_module_wifi.py	Tue Dec 30 21:51:36 2008 -0800
+++ b/bindings/python/ns3_module_wifi.py	Tue Jan 06 13:12:28 2009 +0100
@@ -99,6 +99,8 @@
     module.add_class('WifiChannel', parent=root_module['ns3::Channel'])
     ## wifi-net-device.h: ns3::WifiNetDevice [class]
     module.add_class('WifiNetDevice', parent=root_module['ns3::NetDevice'])
+    ## yans-error-rate-model.h: ns3::YansErrorRateModel [class]
+    module.add_class('YansErrorRateModel', parent=root_module['ns3::ErrorRateModel'])
     ## yans-wifi-channel.h: ns3::YansWifiChannel [class]
     module.add_class('YansWifiChannel', parent=root_module['ns3::WifiChannel'])
     ## aarf-wifi-manager.h: ns3::AarfWifiManager [class]
@@ -189,6 +191,7 @@
     register_Ns3RraaWifiManager_methods(root_module, root_module['ns3::RraaWifiManager'])
     register_Ns3WifiChannel_methods(root_module, root_module['ns3::WifiChannel'])
     register_Ns3WifiNetDevice_methods(root_module, root_module['ns3::WifiNetDevice'])
+    register_Ns3YansErrorRateModel_methods(root_module, root_module['ns3::YansErrorRateModel'])
     register_Ns3YansWifiChannel_methods(root_module, root_module['ns3::YansWifiChannel'])
     register_Ns3AarfWifiManager_methods(root_module, root_module['ns3::AarfWifiManager'])
     return
@@ -2051,13 +2054,13 @@
 def register_Ns3ErrorRateModel_methods(root_module, cls):
     ## error-rate-model.h: ns3::ErrorRateModel::ErrorRateModel(ns3::ErrorRateModel const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::ErrorRateModel const &', 'arg0')])
+    ## error-rate-model.h: ns3::ErrorRateModel::ErrorRateModel() [constructor]
+    cls.add_constructor([])
     ## error-rate-model.h: static ns3::TypeId ns3::ErrorRateModel::GetTypeId() [member function]
     cls.add_method('GetTypeId', 
                    'ns3::TypeId', 
                    [], 
                    is_static=True)
-    ## error-rate-model.h: ns3::ErrorRateModel::ErrorRateModel() [constructor]
-    cls.add_constructor([])
     ## error-rate-model.h: double ns3::ErrorRateModel::CalculateSnr(ns3::WifiMode txMode, double ber) const [member function]
     cls.add_method('CalculateSnr', 
                    'double', 
@@ -2067,7 +2070,7 @@
     cls.add_method('GetChunkSuccessRate', 
                    'double', 
                    [param('ns3::WifiMode', 'mode'), param('double', 'snr'), param('uint32_t', 'nbits')], 
-                   is_const=True)
+                   is_pure_virtual=True, is_const=True, is_virtual=True)
     return
 
 def register_Ns3FriisPropagationLossModel_methods(root_module, cls):
@@ -2736,6 +2739,23 @@
                    visibility='private', is_virtual=True)
     return
 
+def register_Ns3YansErrorRateModel_methods(root_module, cls):
+    ## yans-error-rate-model.h: ns3::YansErrorRateModel::YansErrorRateModel(ns3::YansErrorRateModel const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::YansErrorRateModel const &', 'arg0')])
+    ## yans-error-rate-model.h: static ns3::TypeId ns3::YansErrorRateModel::GetTypeId() [member function]
+    cls.add_method('GetTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_static=True)
+    ## yans-error-rate-model.h: ns3::YansErrorRateModel::YansErrorRateModel() [constructor]
+    cls.add_constructor([])
+    ## yans-error-rate-model.h: double ns3::YansErrorRateModel::GetChunkSuccessRate(ns3::WifiMode mode, double snr, uint32_t nbits) const [member function]
+    cls.add_method('GetChunkSuccessRate', 
+                   'double', 
+                   [param('ns3::WifiMode', 'mode'), param('double', 'snr'), param('uint32_t', 'nbits')], 
+                   is_const=True, is_virtual=True)
+    return
+
 def register_Ns3YansWifiChannel_methods(root_module, cls):
     ## yans-wifi-channel.h: ns3::YansWifiChannel::YansWifiChannel(ns3::YansWifiChannel const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::YansWifiChannel const &', 'arg0')])
--- a/src/devices/wifi/error-rate-model.cc	Tue Dec 30 21:51:36 2008 -0800
+++ b/src/devices/wifi/error-rate-model.cc	Tue Jan 06 13:12:28 2009 +0100
@@ -18,28 +18,17 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 #include "error-rate-model.h"
-#include "wifi-phy.h"
-#include "ns3/log.h"
-
-NS_LOG_COMPONENT_DEFINE ("ErrorRateModel");
 
 namespace ns3 {
 
-NS_OBJECT_ENSURE_REGISTERED (ErrorRateModel);
-
-TypeId 
-ErrorRateModel::GetTypeId (void)
+TypeId ErrorRateModel::GetTypeId (void)
 {
   static TypeId tid = TypeId ("ns3::ErrorRateModel")
     .SetParent<Object> ()
-    .AddConstructor<ErrorRateModel> ()
     ;
   return tid;
 }
 
-ErrorRateModel::ErrorRateModel ()
-{}
-
 double 
 ErrorRateModel::CalculateSnr (WifiMode txMode, double ber) const
 {
@@ -64,231 +53,4 @@
   return low;
 }
 
-
-double 
-ErrorRateModel::Log2 (double val) const
-{
-  return log(val) / log(2.0);
-}
-double 
-ErrorRateModel::GetBpskBer (double snr, uint32_t signalSpread, uint32_t phyRate) const
-{
-  double EbNo = snr * signalSpread / phyRate;
-  double z = sqrt(EbNo);
-  double ber = 0.5 * erfc(z);
-  NS_LOG_INFO ("bpsk snr="<<snr<<" ber="<<ber);
-  return ber;
-}
-double 
-ErrorRateModel::GetQamBer (double snr, unsigned int m, uint32_t signalSpread, uint32_t phyRate) const
-{
-  double EbNo = snr * signalSpread / phyRate;
-  double z = sqrt ((1.5 * Log2 (m) * EbNo) / (m - 1.0));
-  double z1 = ((1.0 - 1.0 / sqrt (m)) * erfc (z)) ;
-  double z2 = 1 - pow ((1-z1), 2.0);
-  double ber = z2 / Log2 (m);
-  NS_LOG_INFO ("Qam m="<<m<<" rate=" << phyRate << " snr="<<snr<<" ber="<<ber);
-  return ber;
-}
-uint32_t
-ErrorRateModel::Factorial (uint32_t k) const
-{
-  uint32_t fact = 1;
-  while (k > 0) 
-    {
-      fact *= k;
-      k--;
-    }
-  return fact;
-}
-double 
-ErrorRateModel::Binomial (uint32_t k, double p, uint32_t n) const
-{
-  double retval = Factorial (n) / (Factorial (k) * Factorial (n-k)) * pow (p, k) * pow (1-p, n-k);
-  return retval;
-}
-double 
-ErrorRateModel::CalculatePdOdd (double ber, unsigned int d) const
-{
-  NS_ASSERT ((d % 2) == 1);
-  unsigned int dstart = (d + 1) / 2;
-  unsigned int dend = d;
-  double pd = 0;
-
-  for (unsigned int i = dstart; i < dend; i++) 
-    {
-      pd += Binomial (i, ber, d);
-    }
-  return pd;
-}
-double 
-ErrorRateModel::CalculatePdEven (double ber, unsigned int d) const
-{
-  NS_ASSERT ((d % 2) == 0);
-  unsigned int dstart = d / 2 + 1;
-  unsigned int dend = d;
-  double pd = 0;
-
-  for (unsigned int i = dstart; i < dend; i++)
-    {
-      pd +=  Binomial (i, ber, d);
-    }
-  pd += 0.5 * Binomial (d / 2, ber, d);
-
-  return pd;
-}
-
-double 
-ErrorRateModel::CalculatePd (double ber, unsigned int d) const
-{
-  double pd;
-  if ((d % 2) == 0) 
-    {
-      pd = CalculatePdEven (ber, d);
-    } 
-  else 
-    {
-      pd = CalculatePdOdd (ber, d);
-    }
-  return pd;
-}
-
-double
-ErrorRateModel::GetFecBpskBer (double snr, double nbits, 
-                         uint32_t signalSpread, uint32_t phyRate,
-                         uint32_t dFree, uint32_t adFree) const
-{
-  double ber = GetBpskBer (snr, signalSpread, phyRate);
-  if (ber == 0.0) 
-    {
-      return 1.0;
-    }
-  double pd = CalculatePd (ber, dFree);
-  double pmu = adFree * pd;
-  pmu = std::min (pmu, 1.0);
-  double pms = pow (1 - pmu, nbits);
-  return pms;
-}
-
-double
-ErrorRateModel::GetFecQamBer (double snr, uint32_t nbits, 
-                       uint32_t signalSpread,
-                       uint32_t phyRate,
-                       uint32_t m, uint32_t dFree,
-                       uint32_t adFree, uint32_t adFreePlusOne) const
-{
-  double ber = GetQamBer (snr, m, signalSpread, phyRate);
-  if (ber == 0.0) 
-    {
-      return 1.0;
-    }
-  /* first term */
-  double pd = CalculatePd (ber, dFree);
-  double pmu = adFree * pd;
-  /* second term */
-  pd = CalculatePd (ber, dFree + 1);
-  pmu += adFreePlusOne * pd;
-  pmu = std::min (pmu, 1.0);
-  double pms = pow (1 - pmu, nbits);
-  return pms;
-}
-
-double 
-ErrorRateModel::GetChunkSuccessRate (WifiMode mode, double snr, uint32_t nbits) const
-{
-  if (mode == WifiPhy::g_6mba)
-    {
-      return GetFecBpskBer (snr, 
-                            nbits,
-                            mode.GetBandwidth (), // signal spread
-                            mode.GetPhyRate (), // phy rate
-                            10, // dFree
-                            11 // adFree
-                            );      
-    }
-  else if (mode == WifiPhy::g_9mba)
-    {
-      return GetFecBpskBer (snr, 
-                            nbits,
-                            mode.GetBandwidth (), // signal spread
-                            mode.GetPhyRate (), // phy rate
-                            5, // dFree
-                            8 // adFree
-                            );
-    }
-  else if (mode == WifiPhy::g_12mba)
-    {
-      return GetFecQamBer (snr, 
-                           nbits,
-                           mode.GetBandwidth (), // signal spread
-                           mode.GetPhyRate (), // phy rate
-                           4,  // m 
-                           10, // dFree
-                           11, // adFree
-                           0   // adFreePlusOne
-                           );
-    }
-  else if (mode == WifiPhy::g_18mba)
-    {
-      return GetFecQamBer (snr, 
-                           nbits,
-                           mode.GetBandwidth (), // signal spread
-                           mode.GetPhyRate (), // phy rate
-                           4, // m
-                           5, // dFree
-                           8, // adFree
-                           31 // adFreePlusOne
-                           );
-    }
-  else if (mode == WifiPhy::g_24mba)
-    {
-      return GetFecQamBer (snr, 
-                           nbits,
-                           mode.GetBandwidth (), // signal spread
-                           mode.GetPhyRate (), // phy rate
-                           16, // m
-                           10, // dFree
-                           11, // adFree
-                           0   // adFreePlusOne
-                           );
-    }
-  else if (mode == WifiPhy::g_36mba)
-    {
-      return GetFecQamBer (snr, 
-                           nbits,
-                           mode.GetBandwidth (), // signal spread
-                           mode.GetPhyRate (), // phy rate
-                           16, // m
-                           5,  // dFree
-                           8,  // adFree
-                           31  // adFreePlusOne
-                           );
-    }
-  else if (mode == WifiPhy::g_48mba)
-    {
-      return GetFecQamBer (snr, 
-                           nbits,
-                           mode.GetBandwidth (), // signal spread
-                           mode.GetPhyRate (), // phy rate
-                           64, // m
-                           6,  // dFree
-                           1,  // adFree
-                           16  // adFreePlusOne
-                           );
-    }
-  else if (mode == WifiPhy::g_54mba)
-    {
-      return GetFecQamBer (snr, 
-                           nbits,
-                           mode.GetBandwidth (), // signal spread
-                           mode.GetPhyRate (), // phy rate
-                           64, // m
-                           5,  // dFree
-                           8,  // adFree
-                           31  // adFreePlusOne
-                           );
-    }
-  return 0;
-}
-
 } // namespace ns3
--- a/src/devices/wifi/error-rate-model.h	Tue Dec 30 21:51:36 2008 -0800
+++ b/src/devices/wifi/error-rate-model.h	Tue Jan 06 13:12:28 2009 +0100
@@ -31,8 +31,6 @@
 public:
   static TypeId GetTypeId (void);
 
-  ErrorRateModel ();
-
   /**
    * \param txMode a specific transmission mode
    * \param ber a target ber
@@ -41,28 +39,9 @@
    */
   double CalculateSnr (WifiMode txMode, double ber) const;
 
-  double GetChunkSuccessRate (WifiMode mode, double snr, uint32_t nbits) const;
-
-private:
-  double Log2 (double val) const;
-  double GetBpskBer (double snr, uint32_t signalSpread, uint32_t phyRate) const;
-  double GetQamBer (double snr, unsigned int m, uint32_t signalSpread, uint32_t phyRate) const;
-  uint32_t Factorial (uint32_t k) const;
-  double Binomial (uint32_t k, double p, uint32_t n) const;
-  double CalculatePdOdd (double ber, unsigned int d) const;
-  double CalculatePdEven (double ber, unsigned int d) const;
-  double CalculatePd (double ber, unsigned int d) const;
-  double GetFecBpskBer (double snr, double nbits, 
-                        uint32_t signalSpread, uint32_t phyRate,
-                        uint32_t dFree, uint32_t adFree) const;
-  double GetFecQamBer (double snr, uint32_t nbits, 
-                       uint32_t signalSpread,
-                       uint32_t phyRate,
-                       uint32_t m, uint32_t dfree,
-                       uint32_t adFree, uint32_t adFreePlusOne) const;
+  virtual double GetChunkSuccessRate (WifiMode mode, double snr, uint32_t nbits) const = 0;
 };
 
-
 } // namespace ns3
 
 #endif /* ERROR_RATE_MODEL_H */
--- a/src/devices/wifi/wifi-phy-test.cc	Tue Dec 30 21:51:36 2008 -0800
+++ b/src/devices/wifi/wifi-phy-test.cc	Tue Jan 06 13:12:28 2009 +0100
@@ -4,6 +4,7 @@
 #include "propagation-loss-model.h"
 #include "propagation-delay-model.h"
 #include "error-rate-model.h"
+#include "yans-error-rate-model.h"
 #include "ns3/ptr.h"
 #include "ns3/mobility-model.h"
 #include "ns3/static-mobility-model.h"
@@ -86,7 +87,7 @@
 
   Ptr<YansWifiPhy> tx = CreateObject<YansWifiPhy> ();
   Ptr<YansWifiPhy> rx = CreateObject<YansWifiPhy> ();
-  Ptr<ErrorRateModel> error = CreateObject<ErrorRateModel> ();
+  Ptr<ErrorRateModel> error = CreateObject<YansErrorRateModel> ();
   tx->SetErrorRateModel (error);
   rx->SetErrorRateModel (error);
   tx->SetChannel (channel);
@@ -217,7 +218,7 @@
   Ptr<YansWifiPhy> txB = CreateObject<YansWifiPhy> ();
   Ptr<YansWifiPhy> rx = CreateObject<YansWifiPhy> ();
 
-  Ptr<ErrorRateModel> error = CreateObject<ErrorRateModel> ();
+  Ptr<ErrorRateModel> error = CreateObject<YansErrorRateModel> ();
   txA->SetErrorRateModel (error);
   txB->SetErrorRateModel (error);
   rx->SetErrorRateModel (error);
--- a/src/devices/wifi/wifi-test.cc	Tue Dec 30 21:51:36 2008 -0800
+++ b/src/devices/wifi/wifi-test.cc	Tue Jan 06 13:12:28 2009 +0100
@@ -8,6 +8,7 @@
 #include "propagation-delay-model.h"
 #include "propagation-loss-model.h"
 #include "error-rate-model.h"
+#include "yans-error-rate-model.h"
 #include "ns3/static-mobility-model.h"
 #include "ns3/node.h"
 #include "ns3/simulator.h"
@@ -52,7 +53,7 @@
   Ptr<WifiMac> mac = m_mac.Create<WifiMac> ();
   Ptr<StaticMobilityModel> mobility = CreateObject<StaticMobilityModel> ();
   Ptr<YansWifiPhy> phy = CreateObject<YansWifiPhy> ();
-  Ptr<ErrorRateModel> error = CreateObject<ErrorRateModel> ();
+  Ptr<ErrorRateModel> error = CreateObject<YansErrorRateModel> ();
   phy->SetErrorRateModel (error);
   phy->SetChannel (channel);
   phy->SetDevice (dev);
--- a/src/devices/wifi/wscript	Tue Dec 30 21:51:36 2008 -0800
+++ b/src/devices/wifi/wscript	Tue Jan 06 13:12:28 2009 +0100
@@ -12,6 +12,7 @@
         'wifi-phy.cc',
         'wifi-phy-state-helper.cc',
         'error-rate-model.cc',
+        'yans-error-rate-model.cc',
         'interference-helper.cc',
         'yans-wifi-phy.cc',
         'yans-wifi-channel.cc',
@@ -75,6 +76,7 @@
         'wifi-phy.h',
         'supported-rates.h',
         'error-rate-model.h',
+        'yans-error-rate-model.h',
         ]
 
     obj = bld.create_ns3_program('wifi-phy-test',
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/yans-error-rate-model.cc	Tue Jan 06 13:12:28 2009 +0100
@@ -0,0 +1,269 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "yans-error-rate-model.h"
+#include "wifi-phy.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("YansErrorRateModel");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (YansErrorRateModel);
+
+TypeId 
+YansErrorRateModel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::YansErrorRateModel")
+    .SetParent<ErrorRateModel> ()
+    .AddConstructor<YansErrorRateModel> ()
+    ;
+  return tid;
+}
+
+YansErrorRateModel::YansErrorRateModel ()
+{}
+
+double 
+YansErrorRateModel::Log2 (double val) const
+{
+  return log(val) / log(2.0);
+}
+double 
+YansErrorRateModel::GetBpskBer (double snr, uint32_t signalSpread, uint32_t phyRate) const
+{
+  double EbNo = snr * signalSpread / phyRate;
+  double z = sqrt(EbNo);
+  double ber = 0.5 * erfc(z);
+  NS_LOG_INFO ("bpsk snr="<<snr<<" ber="<<ber);
+  return ber;
+}
+double 
+YansErrorRateModel::GetQamBer (double snr, unsigned int m, uint32_t signalSpread, uint32_t phyRate) const
+{
+  double EbNo = snr * signalSpread / phyRate;
+  double z = sqrt ((1.5 * Log2 (m) * EbNo) / (m - 1.0));
+  double z1 = ((1.0 - 1.0 / sqrt (m)) * erfc (z)) ;
+  double z2 = 1 - pow ((1-z1), 2.0);
+  double ber = z2 / Log2 (m);
+  NS_LOG_INFO ("Qam m="<<m<<" rate=" << phyRate << " snr="<<snr<<" ber="<<ber);
+  return ber;
+}
+uint32_t
+YansErrorRateModel::Factorial (uint32_t k) const
+{
+  uint32_t fact = 1;
+  while (k > 0) 
+    {
+      fact *= k;
+      k--;
+    }
+  return fact;
+}
+double 
+YansErrorRateModel::Binomial (uint32_t k, double p, uint32_t n) const
+{
+  double retval = Factorial (n) / (Factorial (k) * Factorial (n-k)) * pow (p, k) * pow (1-p, n-k);
+  return retval;
+}
+double 
+YansErrorRateModel::CalculatePdOdd (double ber, unsigned int d) const
+{
+  NS_ASSERT ((d % 2) == 1);
+  unsigned int dstart = (d + 1) / 2;
+  unsigned int dend = d;
+  double pd = 0;
+
+  for (unsigned int i = dstart; i < dend; i++) 
+    {
+      pd += Binomial (i, ber, d);
+    }
+  return pd;
+}
+double 
+YansErrorRateModel::CalculatePdEven (double ber, unsigned int d) const
+{
+  NS_ASSERT ((d % 2) == 0);
+  unsigned int dstart = d / 2 + 1;
+  unsigned int dend = d;
+  double pd = 0;
+
+  for (unsigned int i = dstart; i < dend; i++)
+    {
+      pd +=  Binomial (i, ber, d);
+    }
+  pd += 0.5 * Binomial (d / 2, ber, d);
+
+  return pd;
+}
+
+double 
+YansErrorRateModel::CalculatePd (double ber, unsigned int d) const
+{
+  double pd;
+  if ((d % 2) == 0) 
+    {
+      pd = CalculatePdEven (ber, d);
+    } 
+  else 
+    {
+      pd = CalculatePdOdd (ber, d);
+    }
+  return pd;
+}
+
+double
+YansErrorRateModel::GetFecBpskBer (double snr, double nbits, 
+                         uint32_t signalSpread, uint32_t phyRate,
+                         uint32_t dFree, uint32_t adFree) const
+{
+  double ber = GetBpskBer (snr, signalSpread, phyRate);
+  if (ber == 0.0) 
+    {
+      return 1.0;
+    }
+  double pd = CalculatePd (ber, dFree);
+  double pmu = adFree * pd;
+  pmu = std::min (pmu, 1.0);
+  double pms = pow (1 - pmu, nbits);
+  return pms;
+}
+
+double
+YansErrorRateModel::GetFecQamBer (double snr, uint32_t nbits, 
+                       uint32_t signalSpread,
+                       uint32_t phyRate,
+                       uint32_t m, uint32_t dFree,
+                       uint32_t adFree, uint32_t adFreePlusOne) const
+{
+  double ber = GetQamBer (snr, m, signalSpread, phyRate);
+  if (ber == 0.0) 
+    {
+      return 1.0;
+    }
+  /* first term */
+  double pd = CalculatePd (ber, dFree);
+  double pmu = adFree * pd;
+  /* second term */
+  pd = CalculatePd (ber, dFree + 1);
+  pmu += adFreePlusOne * pd;
+  pmu = std::min (pmu, 1.0);
+  double pms = pow (1 - pmu, nbits);
+  return pms;
+}
+
+double 
+YansErrorRateModel::GetChunkSuccessRate (WifiMode mode, double snr, uint32_t nbits) const
+{
+  if (mode == WifiPhy::g_6mba)
+    {
+      return GetFecBpskBer (snr, 
+                            nbits,
+                            mode.GetBandwidth (), // signal spread
+                            mode.GetPhyRate (), // phy rate
+                            10, // dFree
+                            11 // adFree
+                            );      
+    }
+  else if (mode == WifiPhy::g_9mba)
+    {
+      return GetFecBpskBer (snr, 
+                            nbits,
+                            mode.GetBandwidth (), // signal spread
+                            mode.GetPhyRate (), // phy rate
+                            5, // dFree
+                            8 // adFree
+                            );
+    }
+  else if (mode == WifiPhy::g_12mba)
+    {
+      return GetFecQamBer (snr, 
+                           nbits,
+                           mode.GetBandwidth (), // signal spread
+                           mode.GetPhyRate (), // phy rate
+                           4,  // m 
+                           10, // dFree
+                           11, // adFree
+                           0   // adFreePlusOne
+                           );
+    }
+  else if (mode == WifiPhy::g_18mba)
+    {
+      return GetFecQamBer (snr, 
+                           nbits,
+                           mode.GetBandwidth (), // signal spread
+                           mode.GetPhyRate (), // phy rate
+                           4, // m
+                           5, // dFree
+                           8, // adFree
+                           31 // adFreePlusOne
+                           );
+    }
+  else if (mode == WifiPhy::g_24mba)
+    {
+      return GetFecQamBer (snr, 
+                           nbits,
+                           mode.GetBandwidth (), // signal spread
+                           mode.GetPhyRate (), // phy rate
+                           16, // m
+                           10, // dFree
+                           11, // adFree
+                           0   // adFreePlusOne
+                           );
+    }
+  else if (mode == WifiPhy::g_36mba)
+    {
+      return GetFecQamBer (snr, 
+                           nbits,
+                           mode.GetBandwidth (), // signal spread
+                           mode.GetPhyRate (), // phy rate
+                           16, // m
+                           5,  // dFree
+                           8,  // adFree
+                           31  // adFreePlusOne
+                           );
+    }
+  else if (mode == WifiPhy::g_48mba)
+    {
+      return GetFecQamBer (snr, 
+                           nbits,
+                           mode.GetBandwidth (), // signal spread
+                           mode.GetPhyRate (), // phy rate
+                           64, // m
+                           6,  // dFree
+                           1,  // adFree
+                           16  // adFreePlusOne
+                           );
+    }
+  else if (mode == WifiPhy::g_54mba)
+    {
+      return GetFecQamBer (snr, 
+                           nbits,
+                           mode.GetBandwidth (), // signal spread
+                           mode.GetPhyRate (), // phy rate
+                           64, // m
+                           5,  // dFree
+                           8,  // adFree
+                           31  // adFreePlusOne
+                           );
+    }
+  return 0;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/yans-error-rate-model.h	Tue Jan 06 13:12:28 2009 +0100
@@ -0,0 +1,60 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef YANS_ERROR_RATE_MODEL_H
+#define YANS_ERROR_RATE_MODEL_H
+
+#include <stdint.h>
+#include "wifi-mode.h"
+#include "error-rate-model.h"
+
+namespace ns3 {
+
+class YansErrorRateModel : public ErrorRateModel
+{
+public:
+  static TypeId GetTypeId (void);
+
+  YansErrorRateModel ();
+
+  virtual double GetChunkSuccessRate (WifiMode mode, double snr, uint32_t nbits) const;
+
+private:
+  double Log2 (double val) const;
+  double GetBpskBer (double snr, uint32_t signalSpread, uint32_t phyRate) const;
+  double GetQamBer (double snr, unsigned int m, uint32_t signalSpread, uint32_t phyRate) const;
+  uint32_t Factorial (uint32_t k) const;
+  double Binomial (uint32_t k, double p, uint32_t n) const;
+  double CalculatePdOdd (double ber, unsigned int d) const;
+  double CalculatePdEven (double ber, unsigned int d) const;
+  double CalculatePd (double ber, unsigned int d) const;
+  double GetFecBpskBer (double snr, double nbits, 
+                        uint32_t signalSpread, uint32_t phyRate,
+                        uint32_t dFree, uint32_t adFree) const;
+  double GetFecQamBer (double snr, uint32_t nbits, 
+                       uint32_t signalSpread,
+                       uint32_t phyRate,
+                       uint32_t m, uint32_t dfree,
+                       uint32_t adFree, uint32_t adFreePlusOne) const;
+};
+
+
+} // namespace ns3
+
+#endif /* YANS_ERROR_RATE_MODEL_H */
--- a/src/helper/yans-wifi-helper.cc	Tue Dec 30 21:51:36 2008 -0800
+++ b/src/helper/yans-wifi-helper.cc	Tue Jan 06 13:12:28 2009 +0100
@@ -154,7 +154,7 @@
 YansWifiPhyHelper::Default (void)
 {
   YansWifiPhyHelper helper;
-  helper.SetErrorRateModel ("ns3::ErrorRateModel");
+  helper.SetErrorRateModel ("ns3::YansErrorRateModel");
   return helper;
 }