--- a/CHANGES.html Sun Jul 29 14:29:41 2012 +0200
+++ b/CHANGES.html Tue Jul 31 19:18:23 2012 +0200
@@ -48,12 +48,24 @@
<h2>New API:</h2>
<ul>
-<li></li>
+<li>A RandomVariableStreamHelper has been introduced to assist with
+using the Config subsystem path names to assign fixed stream numbers
+to RandomVariableStream objects.</li>
</ul>
<h2>Changes to existing API:</h2>
<ul>
-<li></li>
+<li>Derived classes of RandomVariable (i.e. the random variable
+implementations) have been ported to a new RandomVariableStream base class.
+<li>For a given distribution DistributionVariable (such as UniformVariable),
+the new class name is DistributionRandomVariable (such as
+UniformRandomVariable). </li>
+<li>The new implementations are also derived from class ns3::Object and
+are handled using the ns-3 smart pointer (Ptr) class. </li>
+<li>The new variable classes also have a new attributed called "Stream"
+which allows them to be assigned to a fix stream index when assigned
+to the underlying pseudo-random stream of numbers.</li>
+</li>
</ul>
<h2>Changes to build system:</h2>
@@ -63,7 +75,11 @@
<h2>Changed behavior:</h2>
<ul>
-<li></li>
+<li>Programs using random variables or models that include random variables
+may exhibit changed output for a given run number or seed, due to a possible
+change in the order in which random variables are assigned to underlying
+pseudo-random sequences. Consult the manual for more information regarding
+this.</li>
</ul>
<hr>
--- a/RELEASE_NOTES Sun Jul 29 14:29:41 2012 +0200
+++ b/RELEASE_NOTES Tue Jul 31 19:18:23 2012 +0200
@@ -21,9 +21,19 @@
New user-visible features
-------------------------
+- A new random variable base class called 'RandomVariableStream', has been
+introduced. This base class derives from ns3::Object, unlike the current
+'RandomVariable' class which is a special type of object in the ns-3
+system to date. By making this class derive from ns3::Object, it can be
+handled with the Ptr class, can carry attributes, and can have its parameters
+and initial state saved in the config-store subsystem. A new attribute
+called "Stream" has been introduced for this class, to allow users to
+better control the assignment of underlying pseudo-random sequences to
+the RandomVariableStream objects (bug 101).
Bugs fixed
----------
+ - bug 101 - random variable initialization
Known issues
------------
--- a/doc/manual/source/how-to-write-tests.rst Sun Jul 29 14:29:41 2012 +0200
+++ b/doc/manual/source/how-to-write-tests.rst Tue Jul 31 19:18:23 2012 +0200
@@ -11,10 +11,11 @@
used for many years by other people, who probably have no idea upon
first glance whether the model is correct. The test code that you
write for your model will help to avoid future regressions in
-the output and will aid future users in understanding the validity
+the output and will aid future users in understanding the verification
and bounds of applicability of your models.
-There are many ways to test that a model is valid. In this chapter,
+There are many ways to verify the correctness of a model's implementation.
+In this section,
we hope to cover some common cases that can be used as a guide to
writing new tests.
@@ -31,15 +32,63 @@
separately in src/test/ directory). You will have to edit the wscript
file in that directory to compile your new code, if it is a new file.
-See the file ``src/template/test/sample-test-suite.cc`` and corresponding
-wscript file in that directory for a simple example, and see the directories
-under ``src/test`` for more complicated examples.
+A program called ``src/create-module.py`` is a good starting point.
+This program can be invoked such as ``create-module.py router`` for
+a hypothetical new module called ``router``. Once you do this, you
+will see a ``router`` directory, and a ``test/router-test-suite.cc``
+test suite. This file can be a starting point for your initial test.
+This is a working test suite, although the actual tests performed are
+trivial. Copy it over to your module's test directory, and do a global
+substitution of "Router" in that file for something pertaining to
+the model that you want to test. You can also edit things such as a
+more descriptive test case name.
+
+You also need to add a block into your wscript to get this test to
+compile:
+
+::
+
+ module_test.source = [
+ 'test/router-test-suite.cc',
+ ]
-*The rest of this chapter remains to be written*
+Before you actually start making this do useful things, it may help
+to try to run the skeleton. Make sure that ns-3 has been configured with
+the "--enable-tests" option. Let's assume that your new test suite
+is called "router" such as here:
+
+::
+
+ RouterTestSuite::RouterTestSuite ()
+ : TestSuite ("router", UNIT)
+
+Try this command:
+
+::
+
+ ./test.py -s router
+
+Output such as below should be produced:
+
+::
+
+ PASS: TestSuite router
+ 1 of 1 tests passed (1 passed, 0 skipped, 0 failed, 0 crashed, 0 valgrind errors)
+
+/* see src/lte/test/test-lte-antenna.cc for a worked example */
How to add an example program to the test suite
***********************************************
+One can "smoke test" that examples compile and run successfully
+to completion (without memory leaks) using the ``examples-to-run.py``
+script located in your module's test directory. Briefly, by including
+an instance of this file in your test directory, you can cause the
+test runner to execute the examples listed. It is usually best to make
+sure that you select examples that have reasonably short run times so as
+to not bog down the tests. See the example in ``src/lte/test/``
+directory.
+
Testing for boolean outcomes
****************************
--- a/doc/manual/source/random-variables.rst Sun Jul 29 14:29:41 2012 +0200
+++ b/doc/manual/source/random-variables.rst Tue Jul 31 19:18:23 2012 +0200
@@ -12,7 +12,7 @@
**************
|ns3| random numbers are provided via instances of
-:cpp:class:`ns3::RandomVariable`.
+:cpp:class:`ns3::RandomVariableStream`.
* by default, |ns3| simulations use a fixed seed; if there is any randomness in
the simulation, each run of the program will yield identical results unless
@@ -21,13 +21,18 @@
* in *ns-3.3* and earlier, |ns3| simulations used a random seed by default; this
marks a change in policy starting with *ns-3.4*.
+* in *ns-3.14* and earlier, |ns3| simulations used a different wrapper class
+ called :cpp:class:`ns3::RandomVariable`. As of *ns-3.15*, this class has been
+ replaced by :cpp:class:`ns3::RandomVariableStream`; the underlying pseudo-random
+ number generator has not changed.
+
* to obtain randomness across multiple simulation runs, you must either set the
seed differently or set the run number differently. To set a seed, call
:cpp:func:`ns3::SeedManager::SetSeed` at the beginning of the program; to set
a run number with the same seed, call :cpp:func:`ns3::SeedManager::SetRun` at
the beginning of the program; see :ref:`seeding-and-independent-replications`.
-* each RandomVariable used in |ns3| has a virtual random number generator
+* each RandomVariableStream used in |ns3| has a virtual random number generator
associated with it; all random variables use either a fixed or random seed
based on the use of the global seed (previous bullet);
@@ -82,14 +87,14 @@
:math:`7.6x10^{22}`. The period of the entire generator is :math:`3.1x10^{57}`.
-Class :cpp:class:`ns3::RandomVariable` is the public interface to this
-underlying random number generator. When users create new ``RandomVariables``
-(such as :cpp:class:`ns3::UniformVariable`,
-:cpp:class:`ns3::ExponentialVariable`, etc.), they create an object that uses
+Class :cpp:class:`ns3::RandomVariableStream` is the public interface to this
+underlying random number generator. When users create new random variables
+(such as :cpp:class:`ns3::UniformRandomVariable`,
+:cpp:class:`ns3::ExponentialRandomVariable`, etc.), they create an object that uses
one of the distinct, independent streams of the random number generator.
-Therefore, each object of type :cpp:class:`ns3::RandomVariable` has,
+Therefore, each object of type :cpp:class:`ns3::RandomVariableStream` has,
conceptually, its own "virtual" RNG. Furthermore, each
-:cpp:class:`ns3::RandomVariable` can be configured to use one of the set of
+:cpp:class:`ns3::RandomVariableStream` can be configured to use one of the set of
substreams drawn from the main stream.
An alternate implementation would be to allow each RandomVariable to have its
@@ -122,8 +127,8 @@
SeedManager::SetSeed (3); // Changes seed from default of 1 to 3
SeedManager::SetRun (7); // Changes run number from default of 1 to 7
// Now, create random variables
- UniformVariable x(0,10);
- ExponentialVariable y(2902);
+ Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable> ();
+ Ptr<ExponentialRandomVariable> y = CreateObject<ExponentialRandomVarlable> ();
...
Which is better, setting a new seed or advancing the substream state? There is
@@ -154,16 +159,16 @@
The above command-line variants make it easy to run lots of different
runs from a shell script by just passing a different RngRun index.
-Class RandomVariable
-********************
+Class RandomVariableStream
+**************************
All random variables should derive from class :cpp:class:`RandomVariable`. This
-base class provides a few static methods for globally configuring the behavior
+base class provides a few methods for globally configuring the behavior
of the random number generator. Derived classes provide API for drawing random
variates from the particular distribution being supported.
-Each RandomVariable created in the simulation is given a generator that is a new
-RNGStream from the underlying PRNG. Used in this manner, the L'Ecuyer
+Each RandomVariableStream created in the simulation is given a generator that is a
+new RNGStream from the underlying PRNG. Used in this manner, the L'Ecuyer
implementation allows for a maximum of :math:`1.8x10^19` random variables. Each
random variable in a single replication can produce up to :math:`7.6x10^22`
random numbers before overlapping.
@@ -171,7 +176,7 @@
Base class public API
*********************
-Below are excerpted a few public methods of class :cpp:class:`RandomVariable`
+Below are excerpted a few public methods of class :cpp:class:`RandomVariableStream`
that access the next value in the substream.::
/**
@@ -181,7 +186,7 @@
double GetValue (void) const;
/**
- * \brief Returns a random integer integer from the underlying distribution
+ * \brief Returns a random integer from the underlying distribution
* \return Integer cast of ::GetValue()
*/
uint32_t GetInteger (void) const;
@@ -193,36 +198,33 @@
************************
The following types of random variables are provided, and are documented in the
-|ns3| Doxygen or by reading ``src/core/model/random-variable.h``. Users can also
-create their own custom random variables by deriving from class
-:cpp:class:`RandomVariable`.
+|ns3| Doxygen or by reading ``src/core/model/random-variable-stream.h``. Users
+can also create their own custom random variables by deriving from class
+:cpp:class:`RandomVariableStream`.
-* class :cpp:class:`UniformVariable`
-* class :cpp:class:`ConstantVariable`
-* class :cpp:class:`SequentialVariable`
-* class :cpp:class:`ExponentialVariable`
-* class :cpp:class:`ParetoVariable`
-* class :cpp:class:`WeibullVariable`
-* class :cpp:class:`NormalVariable`
-* class :cpp:class:`EmpiricalVariable`
-* class :cpp:class:`IntEmpiricalVariable`
-* class :cpp:class:`DeterministicVariable`
-* class :cpp:class:`LogNormalVariable`
-* class :cpp:class:`TriangularVariable`
-* class :cpp:class:`GammaVariable`
-* class :cpp:class:`ErlangVariable`
-* class :cpp:class:`ZipfVariable`
+* class :cpp:class:`UniformRandomVariable`
+* class :cpp:class:`ConstantRandomVariable`
+* class :cpp:class:`SequentialRandomVariable`
+* class :cpp:class:`ExponentialRandomVariable`
+* class :cpp:class:`ParetoRandomVariable`
+* class :cpp:class:`WeibullRandomVariable`
+* class :cpp:class:`NormalRandomVariable`
+* class :cpp:class:`LogNormalRandomVariable`
+* class :cpp:class:`GammaRandomVariable`
+* class :cpp:class:`ErlangRandomVariable`
+* class :cpp:class:`TriangularRandomVariable`
+* class :cpp:class:`ZipfRandomVariable`
+* class :cpp:class:`ZetaRandomVariable`
+* class :cpp:class:`DeterministicRandomVariable`
+* class :cpp:class:`EmpiricalRandomVariable`
-Semantics of RandomVariable objects
-***********************************
+Semantics of RandomVariableStream objects
+*****************************************
-RandomVariable objects have value semantics. This means that they can be passed
-by value to functions. The can also be passed by reference to const.
-RandomVariables do not derive from :cpp:class:`ns3::Object` and we do not use
-smart pointers to manage them; they are either allocated on the stack or else
-users explicitly manage any heap-allocated RandomVariables.
+RandomVariableStream objects derive from :cpp:class:`ns3::Object` and are
+handled by smart pointers.
-RandomVariable objects can also be used in |ns3| attributes, which means
+RandomVariableStream instances can also be used in |ns3| attributes, which means
that values can be set for them through the |ns3| attribute system.
An example is in the propagation models for WifiNetDevice:::
@@ -234,15 +236,15 @@
.AddConstructor<RandomPropagationDelayModel> ()
.AddAttribute ("Variable",
"The random variable which generates random delays (s).",
- RandomVariableValue (UniformVariable (0.0, 1.0)),
- MakeRandomVariableAccessor (&RandomPropagationDelayModel::m_variable),
- MakeRandomVariableChecker ())
+ StringValue ("ns3::UniformRandomVariable"),
+ MakePointerAccessor (&RandomPropagationDelayModel::m_variable),
+ MakePointerChecker<RandomVariableStream> ())
;
return tid;
}
Here, the |ns3| user can change the default random variable for this
-delay model (which is a UniformVariable ranging from 0 to 1) through
+delay model (which is a UniformRandomVariable ranging from 0 to 1) through
the attribute system.
Using other PRNG
@@ -252,10 +254,56 @@
random number generator (e.g., the GNU Scientific Library or the Akaroa
package). Patches are welcome.
-More advanced usage
-*******************
+Setting the stream number
+*************************
+
+The underlying MRG32k3a generator provides 2^64 independent streams.
+In ns-3, these are assigned sequentially starting from the first stream as
+new RandomVariableStream instances make their first call to GetValue().
+
+As a result of how these RandomVariableStream objects are assigned to
+underlying streams, the assignment is sensitive to perturbations of
+the simulation configuration. The consequence is that if any aspect of the
+simulation configuration is changed, the mapping of RandomVariables to
+streams may (or may not) change.
+
+As a concrete example, a user running a comparative study between routing
+protocols may find that the act of changing one routing protocol for another
+will notice that the underlying mobility pattern also changed.
+
+Starting with ns-3.15, some control has been provided to users to allow
+users to optionally fix the assignment of selected RandomVariableStream
+objects to underlying streams. This is the ``Stream`` attribute, part
+of the base class RandomVariableStream.
+
+By partitioning the existing sequence of streams from before:
-*To be completed.*
+::
+
+ <-------------------------------------------------------------------------->
+ stream 0 stream (2^64 - 1)
+
+into two equal-sized sets:
+
+::
+
+ <--------------------------------------------------------------------------->
+ ^ ^^ ^
+ | || |
+ stream 0 stream (2^63 - 1) stream 2^63 stream (2^64 - 1)
+ <- automatically assigned -----><-------- assigned by user----------->
+
+The first 2^63 streams continue to be automatically assigned, while
+the last 2^63 are given stream indices starting with zero up to
+2^63-1.
+
+The assignment of streams to a fixed stream number is optional; instances
+of RandomVariableStream that do not have a stream value assigned will
+be assigned the next one from the pool of automatic streams.
+
+To fix a RandomVariableStream to a particular underlying stream, assign
+its ``Stream`` attribute to a non-negative integer (the default value
+of -1 means that a value will be automatically allocated).
Publishing your results
***********************
--- a/src/antenna/model/antenna-model.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/antenna/model/antenna-model.h Tue Jul 31 19:18:23 2012 +0200
@@ -56,7 +56,7 @@
/**
* this method is expected to be re-implemented by each antenna model
*
- * \param the spherical angles at which the radiation pattern should
+ * \param a the spherical angles at which the radiation pattern should
* be evaluated
*
* \return the power gain in dBi of the antenna radiation pattern at
--- a/src/core/bindings/callbacks_list.py Sun Jul 29 14:29:41 2012 +0200
+++ b/src/core/bindings/callbacks_list.py Tue Jul 31 19:18:23 2012 +0200
@@ -1,5 +1,5 @@
callback_classes = [
- ['void', 'unsigned char*', 'long', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty'],
+ ['void', 'unsigned char*', 'int', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty'],
['void', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty'],
['bool', 'std::string', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty'],
]
--- a/src/core/bindings/modulegen__gcc_ILP32.py Sun Jul 29 14:29:41 2012 +0200
+++ b/src/core/bindings/modulegen__gcc_ILP32.py Tue Jul 31 19:18:23 2012 +0200
@@ -76,10 +76,10 @@
module.add_class('ObjectFactory')
## random-variable.h (module 'core'): ns3::RandomVariable [class]
module.add_class('RandomVariable')
+ ## rng-seed-manager.h (module 'core'): ns3::RngSeedManager [class]
+ module.add_class('RngSeedManager')
## rng-stream.h (module 'core'): ns3::RngStream [class]
module.add_class('RngStream')
- ## random-variable.h (module 'core'): ns3::SeedManager [class]
- module.add_class('SeedManager')
## random-variable.h (module 'core'): ns3::SequentialVariable [class]
module.add_class('SequentialVariable', parent=root_module['ns3::RandomVariable'])
## simple-ref-count.h (module 'core'): ns3::SimpleRefCount<ns3::Object, ns3::ObjectBase, ns3::ObjectDeleter> [class]
@@ -152,12 +152,16 @@
module.add_class('AggregateIterator', outer_class=root_module['ns3::Object'])
## random-variable.h (module 'core'): ns3::ParetoVariable [class]
module.add_class('ParetoVariable', parent=root_module['ns3::RandomVariable'])
+ ## random-variable-stream.h (module 'core'): ns3::RandomVariableStream [class]
+ module.add_class('RandomVariableStream', parent=root_module['ns3::Object'])
## scheduler.h (module 'core'): ns3::Scheduler [class]
module.add_class('Scheduler', parent=root_module['ns3::Object'])
## scheduler.h (module 'core'): ns3::Scheduler::Event [struct]
module.add_class('Event', outer_class=root_module['ns3::Scheduler'])
## scheduler.h (module 'core'): ns3::Scheduler::EventKey [struct]
module.add_class('EventKey', outer_class=root_module['ns3::Scheduler'])
+ ## random-variable-stream.h (module 'core'): ns3::SequentialRandomVariable [class]
+ module.add_class('SequentialRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## simple-ref-count.h (module 'core'): ns3::SimpleRefCount<ns3::AttributeAccessor, ns3::empty, ns3::DefaultDeleter<ns3::AttributeAccessor> > [class]
module.add_class('SimpleRefCount', automatic_type_narrowing=True, template_parameters=['ns3::AttributeAccessor', 'ns3::empty', 'ns3::DefaultDeleter<ns3::AttributeAccessor>'], parent=root_module['ns3::empty'], memory_policy=cppclass.ReferenceCountingMethodsPolicy(incref_method='Ref', decref_method='Unref', peekref_method='GetReferenceCount'))
## simple-ref-count.h (module 'core'): ns3::SimpleRefCount<ns3::AttributeChecker, ns3::empty, ns3::DefaultDeleter<ns3::AttributeChecker> > [class]
@@ -190,8 +194,18 @@
root_module['ns3::Time'].implicitly_converts_to(root_module['ns3::int64x64_t'])
## trace-source-accessor.h (module 'core'): ns3::TraceSourceAccessor [class]
module.add_class('TraceSourceAccessor', parent=root_module['ns3::SimpleRefCount< ns3::TraceSourceAccessor, ns3::empty, ns3::DefaultDeleter<ns3::TraceSourceAccessor> >'])
+ ## random-variable-stream.h (module 'core'): ns3::TriangularRandomVariable [class]
+ module.add_class('TriangularRandomVariable', parent=root_module['ns3::RandomVariableStream'])
+ ## random-variable-stream.h (module 'core'): ns3::UniformRandomVariable [class]
+ module.add_class('UniformRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## wall-clock-synchronizer.h (module 'core'): ns3::WallClockSynchronizer [class]
module.add_class('WallClockSynchronizer', parent=root_module['ns3::Synchronizer'])
+ ## random-variable-stream.h (module 'core'): ns3::WeibullRandomVariable [class]
+ module.add_class('WeibullRandomVariable', parent=root_module['ns3::RandomVariableStream'])
+ ## random-variable-stream.h (module 'core'): ns3::ZetaRandomVariable [class]
+ module.add_class('ZetaRandomVariable', parent=root_module['ns3::RandomVariableStream'])
+ ## random-variable-stream.h (module 'core'): ns3::ZipfRandomVariable [class]
+ module.add_class('ZipfRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## attribute.h (module 'core'): ns3::AttributeAccessor [class]
module.add_class('AttributeAccessor', parent=root_module['ns3::SimpleRefCount< ns3::AttributeAccessor, ns3::empty, ns3::DefaultDeleter<ns3::AttributeAccessor> >'])
## attribute.h (module 'core'): ns3::AttributeChecker [class]
@@ -210,28 +224,44 @@
module.add_class('CallbackImplBase', parent=root_module['ns3::SimpleRefCount< ns3::CallbackImplBase, ns3::empty, ns3::DefaultDeleter<ns3::CallbackImplBase> >'])
## callback.h (module 'core'): ns3::CallbackValue [class]
module.add_class('CallbackValue', parent=root_module['ns3::AttributeValue'])
+ ## random-variable-stream.h (module 'core'): ns3::ConstantRandomVariable [class]
+ module.add_class('ConstantRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## default-simulator-impl.h (module 'core'): ns3::DefaultSimulatorImpl [class]
module.add_class('DefaultSimulatorImpl', parent=root_module['ns3::SimulatorImpl'])
+ ## random-variable-stream.h (module 'core'): ns3::DeterministicRandomVariable [class]
+ module.add_class('DeterministicRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## double.h (module 'core'): ns3::DoubleValue [class]
module.add_class('DoubleValue', parent=root_module['ns3::AttributeValue'])
+ ## random-variable-stream.h (module 'core'): ns3::EmpiricalRandomVariable [class]
+ module.add_class('EmpiricalRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## attribute.h (module 'core'): ns3::EmptyAttributeValue [class]
module.add_class('EmptyAttributeValue', parent=root_module['ns3::AttributeValue'])
## enum.h (module 'core'): ns3::EnumChecker [class]
module.add_class('EnumChecker', parent=root_module['ns3::AttributeChecker'])
## enum.h (module 'core'): ns3::EnumValue [class]
module.add_class('EnumValue', parent=root_module['ns3::AttributeValue'])
+ ## random-variable-stream.h (module 'core'): ns3::ErlangRandomVariable [class]
+ module.add_class('ErlangRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## event-impl.h (module 'core'): ns3::EventImpl [class]
module.add_class('EventImpl', parent=root_module['ns3::SimpleRefCount< ns3::EventImpl, ns3::empty, ns3::DefaultDeleter<ns3::EventImpl> >'])
+ ## random-variable-stream.h (module 'core'): ns3::ExponentialRandomVariable [class]
+ module.add_class('ExponentialRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## unix-fd-reader.h (module 'core'): ns3::FdReader [class]
module.add_class('FdReader', parent=root_module['ns3::SimpleRefCount< ns3::FdReader, ns3::empty, ns3::DefaultDeleter<ns3::FdReader> >'])
+ ## random-variable-stream.h (module 'core'): ns3::GammaRandomVariable [class]
+ module.add_class('GammaRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## heap-scheduler.h (module 'core'): ns3::HeapScheduler [class]
module.add_class('HeapScheduler', parent=root_module['ns3::Scheduler'])
## integer.h (module 'core'): ns3::IntegerValue [class]
module.add_class('IntegerValue', parent=root_module['ns3::AttributeValue'])
## list-scheduler.h (module 'core'): ns3::ListScheduler [class]
module.add_class('ListScheduler', parent=root_module['ns3::Scheduler'])
+ ## random-variable-stream.h (module 'core'): ns3::LogNormalRandomVariable [class]
+ module.add_class('LogNormalRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## map-scheduler.h (module 'core'): ns3::MapScheduler [class]
module.add_class('MapScheduler', parent=root_module['ns3::Scheduler'])
+ ## random-variable-stream.h (module 'core'): ns3::NormalRandomVariable [class]
+ module.add_class('NormalRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## object-factory.h (module 'core'): ns3::ObjectFactoryChecker [class]
module.add_class('ObjectFactoryChecker', parent=root_module['ns3::AttributeChecker'])
## object-factory.h (module 'core'): ns3::ObjectFactoryValue [class]
@@ -242,6 +272,8 @@
module.add_class('ObjectPtrContainerChecker', parent=root_module['ns3::AttributeChecker'])
## object-ptr-container.h (module 'core'): ns3::ObjectPtrContainerValue [class]
module.add_class('ObjectPtrContainerValue', parent=root_module['ns3::AttributeValue'])
+ ## random-variable-stream.h (module 'core'): ns3::ParetoRandomVariable [class]
+ module.add_class('ParetoRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## pointer.h (module 'core'): ns3::PointerChecker [class]
module.add_class('PointerChecker', parent=root_module['ns3::AttributeChecker'])
## pointer.h (module 'core'): ns3::PointerValue [class]
@@ -285,6 +317,10 @@
typehandlers.add_type_alias('void ( * ) ( std::ostream & ) *', 'ns3::LogTimePrinter')
typehandlers.add_type_alias('void ( * ) ( std::ostream & ) **', 'ns3::LogTimePrinter*')
typehandlers.add_type_alias('void ( * ) ( std::ostream & ) *&', 'ns3::LogTimePrinter&')
+ typehandlers.add_type_alias('ns3::RngSeedManager', 'ns3::SeedManager')
+ typehandlers.add_type_alias('ns3::RngSeedManager*', 'ns3::SeedManager*')
+ typehandlers.add_type_alias('ns3::RngSeedManager&', 'ns3::SeedManager&')
+ module.add_typedef(root_module['ns3::RngSeedManager'], 'SeedManager')
typehandlers.add_type_alias('void ( * ) ( std::ostream & ) *', 'ns3::LogNodePrinter')
typehandlers.add_type_alias('void ( * ) ( std::ostream & ) **', 'ns3::LogNodePrinter*')
typehandlers.add_type_alias('void ( * ) ( std::ostream & ) *&', 'ns3::LogNodePrinter&')
@@ -371,8 +407,8 @@
register_Ns3ObjectDeleter_methods(root_module, root_module['ns3::ObjectDeleter'])
register_Ns3ObjectFactory_methods(root_module, root_module['ns3::ObjectFactory'])
register_Ns3RandomVariable_methods(root_module, root_module['ns3::RandomVariable'])
+ register_Ns3RngSeedManager_methods(root_module, root_module['ns3::RngSeedManager'])
register_Ns3RngStream_methods(root_module, root_module['ns3::RngStream'])
- register_Ns3SeedManager_methods(root_module, root_module['ns3::SeedManager'])
register_Ns3SequentialVariable_methods(root_module, root_module['ns3::SequentialVariable'])
register_Ns3SimpleRefCount__Ns3Object_Ns3ObjectBase_Ns3ObjectDeleter_methods(root_module, root_module['ns3::SimpleRefCount< ns3::Object, ns3::ObjectBase, ns3::ObjectDeleter >'])
register_Ns3Simulator_methods(root_module, root_module['ns3::Simulator'])
@@ -406,9 +442,11 @@
register_Ns3Object_methods(root_module, root_module['ns3::Object'])
register_Ns3ObjectAggregateIterator_methods(root_module, root_module['ns3::Object::AggregateIterator'])
register_Ns3ParetoVariable_methods(root_module, root_module['ns3::ParetoVariable'])
+ register_Ns3RandomVariableStream_methods(root_module, root_module['ns3::RandomVariableStream'])
register_Ns3Scheduler_methods(root_module, root_module['ns3::Scheduler'])
register_Ns3SchedulerEvent_methods(root_module, root_module['ns3::Scheduler::Event'])
register_Ns3SchedulerEventKey_methods(root_module, root_module['ns3::Scheduler::EventKey'])
+ register_Ns3SequentialRandomVariable_methods(root_module, root_module['ns3::SequentialRandomVariable'])
register_Ns3SimpleRefCount__Ns3AttributeAccessor_Ns3Empty_Ns3DefaultDeleter__lt__ns3AttributeAccessor__gt___methods(root_module, root_module['ns3::SimpleRefCount< ns3::AttributeAccessor, ns3::empty, ns3::DefaultDeleter<ns3::AttributeAccessor> >'])
register_Ns3SimpleRefCount__Ns3AttributeChecker_Ns3Empty_Ns3DefaultDeleter__lt__ns3AttributeChecker__gt___methods(root_module, root_module['ns3::SimpleRefCount< ns3::AttributeChecker, ns3::empty, ns3::DefaultDeleter<ns3::AttributeChecker> >'])
register_Ns3SimpleRefCount__Ns3AttributeValue_Ns3Empty_Ns3DefaultDeleter__lt__ns3AttributeValue__gt___methods(root_module, root_module['ns3::SimpleRefCount< ns3::AttributeValue, ns3::empty, ns3::DefaultDeleter<ns3::AttributeValue> >'])
@@ -423,7 +461,12 @@
register_Ns3SystemThread_methods(root_module, root_module['ns3::SystemThread'])
register_Ns3Time_methods(root_module, root_module['ns3::Time'])
register_Ns3TraceSourceAccessor_methods(root_module, root_module['ns3::TraceSourceAccessor'])
+ register_Ns3TriangularRandomVariable_methods(root_module, root_module['ns3::TriangularRandomVariable'])
+ register_Ns3UniformRandomVariable_methods(root_module, root_module['ns3::UniformRandomVariable'])
register_Ns3WallClockSynchronizer_methods(root_module, root_module['ns3::WallClockSynchronizer'])
+ register_Ns3WeibullRandomVariable_methods(root_module, root_module['ns3::WeibullRandomVariable'])
+ register_Ns3ZetaRandomVariable_methods(root_module, root_module['ns3::ZetaRandomVariable'])
+ register_Ns3ZipfRandomVariable_methods(root_module, root_module['ns3::ZipfRandomVariable'])
register_Ns3AttributeAccessor_methods(root_module, root_module['ns3::AttributeAccessor'])
register_Ns3AttributeChecker_methods(root_module, root_module['ns3::AttributeChecker'])
register_Ns3AttributeValue_methods(root_module, root_module['ns3::AttributeValue'])
@@ -433,22 +476,31 @@
register_Ns3CallbackChecker_methods(root_module, root_module['ns3::CallbackChecker'])
register_Ns3CallbackImplBase_methods(root_module, root_module['ns3::CallbackImplBase'])
register_Ns3CallbackValue_methods(root_module, root_module['ns3::CallbackValue'])
+ register_Ns3ConstantRandomVariable_methods(root_module, root_module['ns3::ConstantRandomVariable'])
register_Ns3DefaultSimulatorImpl_methods(root_module, root_module['ns3::DefaultSimulatorImpl'])
+ register_Ns3DeterministicRandomVariable_methods(root_module, root_module['ns3::DeterministicRandomVariable'])
register_Ns3DoubleValue_methods(root_module, root_module['ns3::DoubleValue'])
+ register_Ns3EmpiricalRandomVariable_methods(root_module, root_module['ns3::EmpiricalRandomVariable'])
register_Ns3EmptyAttributeValue_methods(root_module, root_module['ns3::EmptyAttributeValue'])
register_Ns3EnumChecker_methods(root_module, root_module['ns3::EnumChecker'])
register_Ns3EnumValue_methods(root_module, root_module['ns3::EnumValue'])
+ register_Ns3ErlangRandomVariable_methods(root_module, root_module['ns3::ErlangRandomVariable'])
register_Ns3EventImpl_methods(root_module, root_module['ns3::EventImpl'])
+ register_Ns3ExponentialRandomVariable_methods(root_module, root_module['ns3::ExponentialRandomVariable'])
register_Ns3FdReader_methods(root_module, root_module['ns3::FdReader'])
+ register_Ns3GammaRandomVariable_methods(root_module, root_module['ns3::GammaRandomVariable'])
register_Ns3HeapScheduler_methods(root_module, root_module['ns3::HeapScheduler'])
register_Ns3IntegerValue_methods(root_module, root_module['ns3::IntegerValue'])
register_Ns3ListScheduler_methods(root_module, root_module['ns3::ListScheduler'])
+ register_Ns3LogNormalRandomVariable_methods(root_module, root_module['ns3::LogNormalRandomVariable'])
register_Ns3MapScheduler_methods(root_module, root_module['ns3::MapScheduler'])
+ register_Ns3NormalRandomVariable_methods(root_module, root_module['ns3::NormalRandomVariable'])
register_Ns3ObjectFactoryChecker_methods(root_module, root_module['ns3::ObjectFactoryChecker'])
register_Ns3ObjectFactoryValue_methods(root_module, root_module['ns3::ObjectFactoryValue'])
register_Ns3ObjectPtrContainerAccessor_methods(root_module, root_module['ns3::ObjectPtrContainerAccessor'])
register_Ns3ObjectPtrContainerChecker_methods(root_module, root_module['ns3::ObjectPtrContainerChecker'])
register_Ns3ObjectPtrContainerValue_methods(root_module, root_module['ns3::ObjectPtrContainerValue'])
+ register_Ns3ParetoRandomVariable_methods(root_module, root_module['ns3::ParetoRandomVariable'])
register_Ns3PointerChecker_methods(root_module, root_module['ns3::PointerChecker'])
register_Ns3PointerValue_methods(root_module, root_module['ns3::PointerValue'])
register_Ns3RandomVariableChecker_methods(root_module, root_module['ns3::RandomVariableChecker'])
@@ -918,127 +970,47 @@
is_const=True)
return
-def register_Ns3RngStream_methods(root_module, cls):
- ## rng-stream.h (module 'core'): ns3::RngStream::RngStream() [constructor]
+def register_Ns3RngSeedManager_methods(root_module, cls):
+ ## rng-seed-manager.h (module 'core'): ns3::RngSeedManager::RngSeedManager() [constructor]
cls.add_constructor([])
- ## rng-stream.h (module 'core'): ns3::RngStream::RngStream(ns3::RngStream const & arg0) [copy constructor]
- cls.add_constructor([param('ns3::RngStream const &', 'arg0')])
- ## rng-stream.h (module 'core'): void ns3::RngStream::AdvanceState(int32_t e, int32_t c) [member function]
- cls.add_method('AdvanceState',
- 'void',
- [param('int32_t', 'e'), param('int32_t', 'c')])
- ## rng-stream.h (module 'core'): static bool ns3::RngStream::CheckSeed(uint32_t const * seed) [member function]
- cls.add_method('CheckSeed',
- 'bool',
- [param('uint32_t const *', 'seed')],
+ ## rng-seed-manager.h (module 'core'): ns3::RngSeedManager::RngSeedManager(ns3::RngSeedManager const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::RngSeedManager const &', 'arg0')])
+ ## rng-seed-manager.h (module 'core'): static uint64_t ns3::RngSeedManager::GetNextStreamIndex() [member function]
+ cls.add_method('GetNextStreamIndex',
+ 'uint64_t',
+ [],
is_static=True)
- ## rng-stream.h (module 'core'): static bool ns3::RngStream::CheckSeed(uint32_t seed) [member function]
- cls.add_method('CheckSeed',
- 'bool',
- [param('uint32_t', 'seed')],
+ ## rng-seed-manager.h (module 'core'): static uint64_t ns3::RngSeedManager::GetRun() [member function]
+ cls.add_method('GetRun',
+ 'uint64_t',
+ [],
is_static=True)
- ## rng-stream.h (module 'core'): static uint32_t ns3::RngStream::GetPackageRun() [member function]
- cls.add_method('GetPackageRun',
+ ## rng-seed-manager.h (module 'core'): static uint32_t ns3::RngSeedManager::GetSeed() [member function]
+ cls.add_method('GetSeed',
'uint32_t',
[],
is_static=True)
- ## rng-stream.h (module 'core'): static void ns3::RngStream::GetPackageSeed(uint32_t * seed) [member function]
- cls.add_method('GetPackageSeed',
+ ## rng-seed-manager.h (module 'core'): static void ns3::RngSeedManager::SetRun(uint64_t run) [member function]
+ cls.add_method('SetRun',
'void',
- [param('uint32_t *', 'seed')],
+ [param('uint64_t', 'run')],
is_static=True)
- ## rng-stream.h (module 'core'): void ns3::RngStream::GetState(uint32_t * seed) const [member function]
- cls.add_method('GetState',
+ ## rng-seed-manager.h (module 'core'): static void ns3::RngSeedManager::SetSeed(uint32_t seed) [member function]
+ cls.add_method('SetSeed',
'void',
- [param('uint32_t *', 'seed')],
- is_const=True)
- ## rng-stream.h (module 'core'): void ns3::RngStream::IncreasedPrecis(bool incp) [member function]
- cls.add_method('IncreasedPrecis',
- 'void',
- [param('bool', 'incp')])
- ## rng-stream.h (module 'core'): void ns3::RngStream::InitializeStream() [member function]
- cls.add_method('InitializeStream',
- 'void',
- [])
- ## rng-stream.h (module 'core'): int32_t ns3::RngStream::RandInt(int32_t i, int32_t j) [member function]
- cls.add_method('RandInt',
- 'int32_t',
- [param('int32_t', 'i'), param('int32_t', 'j')])
+ [param('uint32_t', 'seed')],
+ is_static=True)
+ return
+
+def register_Ns3RngStream_methods(root_module, cls):
+ ## rng-stream.h (module 'core'): ns3::RngStream::RngStream(uint32_t seed, uint64_t stream, uint64_t substream) [constructor]
+ cls.add_constructor([param('uint32_t', 'seed'), param('uint64_t', 'stream'), param('uint64_t', 'substream')])
+ ## rng-stream.h (module 'core'): ns3::RngStream::RngStream(ns3::RngStream const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::RngStream const &', 'arg0')])
## rng-stream.h (module 'core'): double ns3::RngStream::RandU01() [member function]
cls.add_method('RandU01',
'double',
[])
- ## rng-stream.h (module 'core'): void ns3::RngStream::ResetNextSubstream() [member function]
- cls.add_method('ResetNextSubstream',
- 'void',
- [])
- ## rng-stream.h (module 'core'): void ns3::RngStream::ResetNthSubstream(uint32_t N) [member function]
- cls.add_method('ResetNthSubstream',
- 'void',
- [param('uint32_t', 'N')])
- ## rng-stream.h (module 'core'): void ns3::RngStream::ResetStartStream() [member function]
- cls.add_method('ResetStartStream',
- 'void',
- [])
- ## rng-stream.h (module 'core'): void ns3::RngStream::ResetStartSubstream() [member function]
- cls.add_method('ResetStartSubstream',
- 'void',
- [])
- ## rng-stream.h (module 'core'): void ns3::RngStream::SetAntithetic(bool a) [member function]
- cls.add_method('SetAntithetic',
- 'void',
- [param('bool', 'a')])
- ## rng-stream.h (module 'core'): static void ns3::RngStream::SetPackageRun(uint32_t run) [member function]
- cls.add_method('SetPackageRun',
- 'void',
- [param('uint32_t', 'run')],
- is_static=True)
- ## rng-stream.h (module 'core'): static bool ns3::RngStream::SetPackageSeed(uint32_t seed) [member function]
- cls.add_method('SetPackageSeed',
- 'bool',
- [param('uint32_t', 'seed')],
- is_static=True)
- ## rng-stream.h (module 'core'): static bool ns3::RngStream::SetPackageSeed(uint32_t const * seed) [member function]
- cls.add_method('SetPackageSeed',
- 'bool',
- [param('uint32_t const *', 'seed')],
- is_static=True)
- ## rng-stream.h (module 'core'): bool ns3::RngStream::SetSeeds(uint32_t const * seed) [member function]
- cls.add_method('SetSeeds',
- 'bool',
- [param('uint32_t const *', 'seed')])
- return
-
-def register_Ns3SeedManager_methods(root_module, cls):
- ## random-variable.h (module 'core'): ns3::SeedManager::SeedManager() [constructor]
- cls.add_constructor([])
- ## random-variable.h (module 'core'): ns3::SeedManager::SeedManager(ns3::SeedManager const & arg0) [copy constructor]
- cls.add_constructor([param('ns3::SeedManager const &', 'arg0')])
- ## random-variable.h (module 'core'): static bool ns3::SeedManager::CheckSeed(uint32_t seed) [member function]
- cls.add_method('CheckSeed',
- 'bool',
- [param('uint32_t', 'seed')],
- is_static=True)
- ## random-variable.h (module 'core'): static uint32_t ns3::SeedManager::GetRun() [member function]
- cls.add_method('GetRun',
- 'uint32_t',
- [],
- is_static=True)
- ## random-variable.h (module 'core'): static uint32_t ns3::SeedManager::GetSeed() [member function]
- cls.add_method('GetSeed',
- 'uint32_t',
- [],
- is_static=True)
- ## random-variable.h (module 'core'): static void ns3::SeedManager::SetRun(uint32_t run) [member function]
- cls.add_method('SetRun',
- 'void',
- [param('uint32_t', 'run')],
- is_static=True)
- ## random-variable.h (module 'core'): static void ns3::SeedManager::SetSeed(uint32_t seed) [member function]
- cls.add_method('SetSeed',
- 'void',
- [param('uint32_t', 'seed')],
- is_static=True)
return
def register_Ns3SequentialVariable_methods(root_module, cls):
@@ -1886,6 +1858,49 @@
cls.add_constructor([param('std::pair< double, double >', 'params'), param('double', 'b')])
return
+def register_Ns3RandomVariableStream_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::RandomVariableStream::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::RandomVariableStream::RandomVariableStream() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): void ns3::RandomVariableStream::SetStream(int64_t stream) [member function]
+ cls.add_method('SetStream',
+ 'void',
+ [param('int64_t', 'stream')])
+ ## random-variable-stream.h (module 'core'): int64_t ns3::RandomVariableStream::GetStream() const [member function]
+ cls.add_method('GetStream',
+ 'int64_t',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): void ns3::RandomVariableStream::SetAntithetic(bool isAntithetic) [member function]
+ cls.add_method('SetAntithetic',
+ 'void',
+ [param('bool', 'isAntithetic')])
+ ## random-variable-stream.h (module 'core'): bool ns3::RandomVariableStream::IsAntithetic() const [member function]
+ cls.add_method('IsAntithetic',
+ 'bool',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::RandomVariableStream::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_pure_virtual=True, is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::RandomVariableStream::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_pure_virtual=True, is_virtual=True)
+ ## random-variable-stream.h (module 'core'): ns3::RngStream * ns3::RandomVariableStream::Peek() const [member function]
+ cls.add_method('Peek',
+ 'ns3::RngStream *',
+ [],
+ is_const=True, visibility='protected')
+ return
+
def register_Ns3Scheduler_methods(root_module, cls):
## scheduler.h (module 'core'): ns3::Scheduler::Scheduler() [constructor]
cls.add_constructor([])
@@ -1951,6 +1966,46 @@
cls.add_instance_attribute('m_uid', 'uint32_t', is_const=False)
return
+def register_Ns3SequentialRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::SequentialRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::SequentialRandomVariable::SequentialRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::SequentialRandomVariable::GetMin() const [member function]
+ cls.add_method('GetMin',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::SequentialRandomVariable::GetMax() const [member function]
+ cls.add_method('GetMax',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): ns3::Ptr<ns3::RandomVariableStream> ns3::SequentialRandomVariable::GetIncrement() const [member function]
+ cls.add_method('GetIncrement',
+ 'ns3::Ptr< ns3::RandomVariableStream >',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::SequentialRandomVariable::GetConsecutive() const [member function]
+ cls.add_method('GetConsecutive',
+ 'uint32_t',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::SequentialRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::SequentialRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3SimpleRefCount__Ns3AttributeAccessor_Ns3Empty_Ns3DefaultDeleter__lt__ns3AttributeAccessor__gt___methods(root_module, cls):
## simple-ref-count.h (module 'core'): ns3::SimpleRefCount<ns3::AttributeAccessor, ns3::empty, ns3::DefaultDeleter<ns3::AttributeAccessor> >::SimpleRefCount() [constructor]
cls.add_constructor([])
@@ -2466,6 +2521,87 @@
is_pure_virtual=True, is_const=True, is_virtual=True)
return
+def register_Ns3TriangularRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::TriangularRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::TriangularRandomVariable::TriangularRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::TriangularRandomVariable::GetMean() const [member function]
+ cls.add_method('GetMean',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::TriangularRandomVariable::GetMin() const [member function]
+ cls.add_method('GetMin',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::TriangularRandomVariable::GetMax() const [member function]
+ cls.add_method('GetMax',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::TriangularRandomVariable::GetValue(double mean, double min, double max) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'mean'), param('double', 'min'), param('double', 'max')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::TriangularRandomVariable::GetInteger(uint32_t mean, uint32_t min, uint32_t max) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'mean'), param('uint32_t', 'min'), param('uint32_t', 'max')])
+ ## random-variable-stream.h (module 'core'): double ns3::TriangularRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::TriangularRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
+def register_Ns3UniformRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::UniformRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::UniformRandomVariable::UniformRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::UniformRandomVariable::GetMin() const [member function]
+ cls.add_method('GetMin',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::UniformRandomVariable::GetMax() const [member function]
+ cls.add_method('GetMax',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::UniformRandomVariable::GetValue(double min, double max) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'min'), param('double', 'max')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::UniformRandomVariable::GetInteger(uint32_t min, uint32_t max) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'min'), param('uint32_t', 'max')])
+ ## random-variable-stream.h (module 'core'): double ns3::UniformRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::UniformRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3WallClockSynchronizer_methods(root_module, cls):
## wall-clock-synchronizer.h (module 'core'): ns3::WallClockSynchronizer::WallClockSynchronizer(ns3::WallClockSynchronizer const & arg0) [copy constructor]
cls.add_constructor([param('ns3::WallClockSynchronizer const &', 'arg0')])
@@ -2564,6 +2700,120 @@
visibility='protected')
return
+def register_Ns3WeibullRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::WeibullRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::WeibullRandomVariable::WeibullRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::WeibullRandomVariable::GetScale() const [member function]
+ cls.add_method('GetScale',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::WeibullRandomVariable::GetShape() const [member function]
+ cls.add_method('GetShape',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::WeibullRandomVariable::GetBound() const [member function]
+ cls.add_method('GetBound',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::WeibullRandomVariable::GetValue(double scale, double shape, double bound) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'scale'), param('double', 'shape'), param('double', 'bound')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::WeibullRandomVariable::GetInteger(uint32_t scale, uint32_t shape, uint32_t bound) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'scale'), param('uint32_t', 'shape'), param('uint32_t', 'bound')])
+ ## random-variable-stream.h (module 'core'): double ns3::WeibullRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::WeibullRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
+def register_Ns3ZetaRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::ZetaRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::ZetaRandomVariable::ZetaRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::ZetaRandomVariable::GetAlpha() const [member function]
+ cls.add_method('GetAlpha',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ZetaRandomVariable::GetValue(double alpha) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'alpha')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ZetaRandomVariable::GetInteger(uint32_t alpha) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'alpha')])
+ ## random-variable-stream.h (module 'core'): double ns3::ZetaRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ZetaRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
+def register_Ns3ZipfRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::ZipfRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::ZipfRandomVariable::ZipfRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ZipfRandomVariable::GetN() const [member function]
+ cls.add_method('GetN',
+ 'uint32_t',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ZipfRandomVariable::GetAlpha() const [member function]
+ cls.add_method('GetAlpha',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ZipfRandomVariable::GetValue(uint32_t n, double alpha) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('uint32_t', 'n'), param('double', 'alpha')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ZipfRandomVariable::GetInteger(uint32_t n, uint32_t alpha) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'n'), param('uint32_t', 'alpha')])
+ ## random-variable-stream.h (module 'core'): double ns3::ZipfRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ZipfRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3AttributeAccessor_methods(root_module, cls):
## attribute.h (module 'core'): ns3::AttributeAccessor::AttributeAccessor(ns3::AttributeAccessor const & arg0) [copy constructor]
cls.add_constructor([param('ns3::AttributeAccessor const &', 'arg0')])
@@ -2780,6 +3030,39 @@
[param('ns3::CallbackBase', 'base')])
return
+def register_Ns3ConstantRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::ConstantRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::ConstantRandomVariable::ConstantRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::ConstantRandomVariable::GetConstant() const [member function]
+ cls.add_method('GetConstant',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ConstantRandomVariable::GetValue(double constant) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'constant')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ConstantRandomVariable::GetInteger(uint32_t constant) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'constant')])
+ ## random-variable-stream.h (module 'core'): double ns3::ConstantRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ConstantRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3DefaultSimulatorImpl_methods(root_module, cls):
## default-simulator-impl.h (module 'core'): ns3::DefaultSimulatorImpl::DefaultSimulatorImpl(ns3::DefaultSimulatorImpl const & arg0) [copy constructor]
cls.add_constructor([param('ns3::DefaultSimulatorImpl const &', 'arg0')])
@@ -2887,6 +3170,30 @@
visibility='private', is_virtual=True)
return
+def register_Ns3DeterministicRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::DeterministicRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::DeterministicRandomVariable::DeterministicRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): void ns3::DeterministicRandomVariable::SetValueArray(double * values, uint64_t length) [member function]
+ cls.add_method('SetValueArray',
+ 'void',
+ [param('double *', 'values'), param('uint64_t', 'length')])
+ ## random-variable-stream.h (module 'core'): double ns3::DeterministicRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::DeterministicRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3DoubleValue_methods(root_module, cls):
## double.h (module 'core'): ns3::DoubleValue::DoubleValue() [constructor]
cls.add_constructor([])
@@ -2920,6 +3227,40 @@
[param('double const &', 'value')])
return
+def register_Ns3EmpiricalRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): ns3::EmpiricalRandomVariable::EmpiricalRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): void ns3::EmpiricalRandomVariable::CDF(double v, double c) [member function]
+ cls.add_method('CDF',
+ 'void',
+ [param('double', 'v'), param('double', 'c')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::EmpiricalRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::EmpiricalRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): double ns3::EmpiricalRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): double ns3::EmpiricalRandomVariable::Interpolate(double arg0, double arg1, double arg2, double arg3, double arg4) [member function]
+ cls.add_method('Interpolate',
+ 'double',
+ [param('double', 'arg0'), param('double', 'arg1'), param('double', 'arg2'), param('double', 'arg3'), param('double', 'arg4')],
+ visibility='private', is_virtual=True)
+ ## random-variable-stream.h (module 'core'): void ns3::EmpiricalRandomVariable::Validate() [member function]
+ cls.add_method('Validate',
+ 'void',
+ [],
+ visibility='private', is_virtual=True)
+ return
+
def register_Ns3EmptyAttributeValue_methods(root_module, cls):
## attribute.h (module 'core'): ns3::EmptyAttributeValue::EmptyAttributeValue(ns3::EmptyAttributeValue const & arg0) [copy constructor]
cls.add_constructor([param('ns3::EmptyAttributeValue const &', 'arg0')])
@@ -3020,6 +3361,44 @@
[param('int', 'v')])
return
+def register_Ns3ErlangRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::ErlangRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::ErlangRandomVariable::ErlangRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ErlangRandomVariable::GetK() const [member function]
+ cls.add_method('GetK',
+ 'uint32_t',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ErlangRandomVariable::GetLambda() const [member function]
+ cls.add_method('GetLambda',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ErlangRandomVariable::GetValue(uint32_t k, double lambda) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('uint32_t', 'k'), param('double', 'lambda')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ErlangRandomVariable::GetInteger(uint32_t k, uint32_t lambda) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'k'), param('uint32_t', 'lambda')])
+ ## random-variable-stream.h (module 'core'): double ns3::ErlangRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ErlangRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3EventImpl_methods(root_module, cls):
## event-impl.h (module 'core'): ns3::EventImpl::EventImpl(ns3::EventImpl const & arg0) [copy constructor]
cls.add_constructor([param('ns3::EventImpl const &', 'arg0')])
@@ -3044,6 +3423,44 @@
is_pure_virtual=True, visibility='protected', is_virtual=True)
return
+def register_Ns3ExponentialRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::ExponentialRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::ExponentialRandomVariable::ExponentialRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::ExponentialRandomVariable::GetMean() const [member function]
+ cls.add_method('GetMean',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ExponentialRandomVariable::GetBound() const [member function]
+ cls.add_method('GetBound',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ExponentialRandomVariable::GetValue(double mean, double bound) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'mean'), param('double', 'bound')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ExponentialRandomVariable::GetInteger(uint32_t mean, uint32_t bound) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'mean'), param('uint32_t', 'bound')])
+ ## random-variable-stream.h (module 'core'): double ns3::ExponentialRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ExponentialRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3FdReader_methods(root_module, cls):
## unix-fd-reader.h (module 'core'): ns3::FdReader::FdReader(ns3::FdReader const & arg0) [copy constructor]
cls.add_constructor([param('ns3::FdReader const &', 'arg0')])
@@ -3064,6 +3481,44 @@
is_pure_virtual=True, visibility='protected', is_virtual=True)
return
+def register_Ns3GammaRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::GammaRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::GammaRandomVariable::GammaRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::GammaRandomVariable::GetAlpha() const [member function]
+ cls.add_method('GetAlpha',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::GammaRandomVariable::GetBeta() const [member function]
+ cls.add_method('GetBeta',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::GammaRandomVariable::GetValue(double alpha, double beta) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'alpha'), param('double', 'beta')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::GammaRandomVariable::GetInteger(uint32_t alpha, uint32_t beta) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'alpha'), param('uint32_t', 'beta')])
+ ## random-variable-stream.h (module 'core'): double ns3::GammaRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::GammaRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3HeapScheduler_methods(root_module, cls):
## heap-scheduler.h (module 'core'): ns3::HeapScheduler::HeapScheduler(ns3::HeapScheduler const & arg0) [copy constructor]
cls.add_constructor([param('ns3::HeapScheduler const &', 'arg0')])
@@ -3171,6 +3626,44 @@
is_virtual=True)
return
+def register_Ns3LogNormalRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::LogNormalRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::LogNormalRandomVariable::LogNormalRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::LogNormalRandomVariable::GetMu() const [member function]
+ cls.add_method('GetMu',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::LogNormalRandomVariable::GetSigma() const [member function]
+ cls.add_method('GetSigma',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::LogNormalRandomVariable::GetValue(double mu, double sigma) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'mu'), param('double', 'sigma')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::LogNormalRandomVariable::GetInteger(uint32_t mu, uint32_t sigma) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'mu'), param('uint32_t', 'sigma')])
+ ## random-variable-stream.h (module 'core'): double ns3::LogNormalRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::LogNormalRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3MapScheduler_methods(root_module, cls):
## map-scheduler.h (module 'core'): ns3::MapScheduler::MapScheduler(ns3::MapScheduler const & arg0) [copy constructor]
cls.add_constructor([param('ns3::MapScheduler const &', 'arg0')])
@@ -3208,6 +3701,51 @@
is_virtual=True)
return
+def register_Ns3NormalRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): ns3::NormalRandomVariable::INFINITE_VALUE [variable]
+ cls.add_static_attribute('INFINITE_VALUE', 'double const', is_const=True)
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::NormalRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::NormalRandomVariable::NormalRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::NormalRandomVariable::GetMean() const [member function]
+ cls.add_method('GetMean',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::NormalRandomVariable::GetVariance() const [member function]
+ cls.add_method('GetVariance',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::NormalRandomVariable::GetBound() const [member function]
+ cls.add_method('GetBound',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::NormalRandomVariable::GetValue(double mean, double variance, double bound) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'mean'), param('double', 'variance'), param('double', 'bound')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::NormalRandomVariable::GetInteger(uint32_t mean, uint32_t variance, uint32_t bound) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'mean'), param('uint32_t', 'variance'), param('uint32_t', 'bound')])
+ ## random-variable-stream.h (module 'core'): double ns3::NormalRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::NormalRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3ObjectFactoryChecker_methods(root_module, cls):
## object-factory.h (module 'core'): ns3::ObjectFactoryChecker::ObjectFactoryChecker() [constructor]
cls.add_constructor([])
@@ -3339,6 +3877,49 @@
is_const=True, is_virtual=True)
return
+def register_Ns3ParetoRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::ParetoRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::ParetoRandomVariable::ParetoRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::ParetoRandomVariable::GetMean() const [member function]
+ cls.add_method('GetMean',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ParetoRandomVariable::GetShape() const [member function]
+ cls.add_method('GetShape',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ParetoRandomVariable::GetBound() const [member function]
+ cls.add_method('GetBound',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ParetoRandomVariable::GetValue(double mean, double shape, double bound) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'mean'), param('double', 'shape'), param('double', 'bound')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ParetoRandomVariable::GetInteger(uint32_t mean, uint32_t shape, uint32_t bound) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'mean'), param('uint32_t', 'shape'), param('uint32_t', 'bound')])
+ ## random-variable-stream.h (module 'core'): double ns3::ParetoRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ParetoRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3PointerChecker_methods(root_module, cls):
## pointer.h (module 'core'): ns3::PointerChecker::PointerChecker() [constructor]
cls.add_constructor([])
--- a/src/core/bindings/modulegen__gcc_LP64.py Sun Jul 29 14:29:41 2012 +0200
+++ b/src/core/bindings/modulegen__gcc_LP64.py Tue Jul 31 19:18:23 2012 +0200
@@ -76,10 +76,10 @@
module.add_class('ObjectFactory')
## random-variable.h (module 'core'): ns3::RandomVariable [class]
module.add_class('RandomVariable')
+ ## rng-seed-manager.h (module 'core'): ns3::RngSeedManager [class]
+ module.add_class('RngSeedManager')
## rng-stream.h (module 'core'): ns3::RngStream [class]
module.add_class('RngStream')
- ## random-variable.h (module 'core'): ns3::SeedManager [class]
- module.add_class('SeedManager')
## random-variable.h (module 'core'): ns3::SequentialVariable [class]
module.add_class('SequentialVariable', parent=root_module['ns3::RandomVariable'])
## simple-ref-count.h (module 'core'): ns3::SimpleRefCount<ns3::Object, ns3::ObjectBase, ns3::ObjectDeleter> [class]
@@ -152,12 +152,16 @@
module.add_class('AggregateIterator', outer_class=root_module['ns3::Object'])
## random-variable.h (module 'core'): ns3::ParetoVariable [class]
module.add_class('ParetoVariable', parent=root_module['ns3::RandomVariable'])
+ ## random-variable-stream.h (module 'core'): ns3::RandomVariableStream [class]
+ module.add_class('RandomVariableStream', parent=root_module['ns3::Object'])
## scheduler.h (module 'core'): ns3::Scheduler [class]
module.add_class('Scheduler', parent=root_module['ns3::Object'])
## scheduler.h (module 'core'): ns3::Scheduler::Event [struct]
module.add_class('Event', outer_class=root_module['ns3::Scheduler'])
## scheduler.h (module 'core'): ns3::Scheduler::EventKey [struct]
module.add_class('EventKey', outer_class=root_module['ns3::Scheduler'])
+ ## random-variable-stream.h (module 'core'): ns3::SequentialRandomVariable [class]
+ module.add_class('SequentialRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## simple-ref-count.h (module 'core'): ns3::SimpleRefCount<ns3::AttributeAccessor, ns3::empty, ns3::DefaultDeleter<ns3::AttributeAccessor> > [class]
module.add_class('SimpleRefCount', automatic_type_narrowing=True, template_parameters=['ns3::AttributeAccessor', 'ns3::empty', 'ns3::DefaultDeleter<ns3::AttributeAccessor>'], parent=root_module['ns3::empty'], memory_policy=cppclass.ReferenceCountingMethodsPolicy(incref_method='Ref', decref_method='Unref', peekref_method='GetReferenceCount'))
## simple-ref-count.h (module 'core'): ns3::SimpleRefCount<ns3::AttributeChecker, ns3::empty, ns3::DefaultDeleter<ns3::AttributeChecker> > [class]
@@ -190,8 +194,18 @@
root_module['ns3::Time'].implicitly_converts_to(root_module['ns3::int64x64_t'])
## trace-source-accessor.h (module 'core'): ns3::TraceSourceAccessor [class]
module.add_class('TraceSourceAccessor', parent=root_module['ns3::SimpleRefCount< ns3::TraceSourceAccessor, ns3::empty, ns3::DefaultDeleter<ns3::TraceSourceAccessor> >'])
+ ## random-variable-stream.h (module 'core'): ns3::TriangularRandomVariable [class]
+ module.add_class('TriangularRandomVariable', parent=root_module['ns3::RandomVariableStream'])
+ ## random-variable-stream.h (module 'core'): ns3::UniformRandomVariable [class]
+ module.add_class('UniformRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## wall-clock-synchronizer.h (module 'core'): ns3::WallClockSynchronizer [class]
module.add_class('WallClockSynchronizer', parent=root_module['ns3::Synchronizer'])
+ ## random-variable-stream.h (module 'core'): ns3::WeibullRandomVariable [class]
+ module.add_class('WeibullRandomVariable', parent=root_module['ns3::RandomVariableStream'])
+ ## random-variable-stream.h (module 'core'): ns3::ZetaRandomVariable [class]
+ module.add_class('ZetaRandomVariable', parent=root_module['ns3::RandomVariableStream'])
+ ## random-variable-stream.h (module 'core'): ns3::ZipfRandomVariable [class]
+ module.add_class('ZipfRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## attribute.h (module 'core'): ns3::AttributeAccessor [class]
module.add_class('AttributeAccessor', parent=root_module['ns3::SimpleRefCount< ns3::AttributeAccessor, ns3::empty, ns3::DefaultDeleter<ns3::AttributeAccessor> >'])
## attribute.h (module 'core'): ns3::AttributeChecker [class]
@@ -210,28 +224,44 @@
module.add_class('CallbackImplBase', parent=root_module['ns3::SimpleRefCount< ns3::CallbackImplBase, ns3::empty, ns3::DefaultDeleter<ns3::CallbackImplBase> >'])
## callback.h (module 'core'): ns3::CallbackValue [class]
module.add_class('CallbackValue', parent=root_module['ns3::AttributeValue'])
+ ## random-variable-stream.h (module 'core'): ns3::ConstantRandomVariable [class]
+ module.add_class('ConstantRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## default-simulator-impl.h (module 'core'): ns3::DefaultSimulatorImpl [class]
module.add_class('DefaultSimulatorImpl', parent=root_module['ns3::SimulatorImpl'])
+ ## random-variable-stream.h (module 'core'): ns3::DeterministicRandomVariable [class]
+ module.add_class('DeterministicRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## double.h (module 'core'): ns3::DoubleValue [class]
module.add_class('DoubleValue', parent=root_module['ns3::AttributeValue'])
+ ## random-variable-stream.h (module 'core'): ns3::EmpiricalRandomVariable [class]
+ module.add_class('EmpiricalRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## attribute.h (module 'core'): ns3::EmptyAttributeValue [class]
module.add_class('EmptyAttributeValue', parent=root_module['ns3::AttributeValue'])
## enum.h (module 'core'): ns3::EnumChecker [class]
module.add_class('EnumChecker', parent=root_module['ns3::AttributeChecker'])
## enum.h (module 'core'): ns3::EnumValue [class]
module.add_class('EnumValue', parent=root_module['ns3::AttributeValue'])
+ ## random-variable-stream.h (module 'core'): ns3::ErlangRandomVariable [class]
+ module.add_class('ErlangRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## event-impl.h (module 'core'): ns3::EventImpl [class]
module.add_class('EventImpl', parent=root_module['ns3::SimpleRefCount< ns3::EventImpl, ns3::empty, ns3::DefaultDeleter<ns3::EventImpl> >'])
+ ## random-variable-stream.h (module 'core'): ns3::ExponentialRandomVariable [class]
+ module.add_class('ExponentialRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## unix-fd-reader.h (module 'core'): ns3::FdReader [class]
module.add_class('FdReader', parent=root_module['ns3::SimpleRefCount< ns3::FdReader, ns3::empty, ns3::DefaultDeleter<ns3::FdReader> >'])
+ ## random-variable-stream.h (module 'core'): ns3::GammaRandomVariable [class]
+ module.add_class('GammaRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## heap-scheduler.h (module 'core'): ns3::HeapScheduler [class]
module.add_class('HeapScheduler', parent=root_module['ns3::Scheduler'])
## integer.h (module 'core'): ns3::IntegerValue [class]
module.add_class('IntegerValue', parent=root_module['ns3::AttributeValue'])
## list-scheduler.h (module 'core'): ns3::ListScheduler [class]
module.add_class('ListScheduler', parent=root_module['ns3::Scheduler'])
+ ## random-variable-stream.h (module 'core'): ns3::LogNormalRandomVariable [class]
+ module.add_class('LogNormalRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## map-scheduler.h (module 'core'): ns3::MapScheduler [class]
module.add_class('MapScheduler', parent=root_module['ns3::Scheduler'])
+ ## random-variable-stream.h (module 'core'): ns3::NormalRandomVariable [class]
+ module.add_class('NormalRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## object-factory.h (module 'core'): ns3::ObjectFactoryChecker [class]
module.add_class('ObjectFactoryChecker', parent=root_module['ns3::AttributeChecker'])
## object-factory.h (module 'core'): ns3::ObjectFactoryValue [class]
@@ -242,6 +272,8 @@
module.add_class('ObjectPtrContainerChecker', parent=root_module['ns3::AttributeChecker'])
## object-ptr-container.h (module 'core'): ns3::ObjectPtrContainerValue [class]
module.add_class('ObjectPtrContainerValue', parent=root_module['ns3::AttributeValue'])
+ ## random-variable-stream.h (module 'core'): ns3::ParetoRandomVariable [class]
+ module.add_class('ParetoRandomVariable', parent=root_module['ns3::RandomVariableStream'])
## pointer.h (module 'core'): ns3::PointerChecker [class]
module.add_class('PointerChecker', parent=root_module['ns3::AttributeChecker'])
## pointer.h (module 'core'): ns3::PointerValue [class]
@@ -285,6 +317,10 @@
typehandlers.add_type_alias('void ( * ) ( std::ostream & ) *', 'ns3::LogTimePrinter')
typehandlers.add_type_alias('void ( * ) ( std::ostream & ) **', 'ns3::LogTimePrinter*')
typehandlers.add_type_alias('void ( * ) ( std::ostream & ) *&', 'ns3::LogTimePrinter&')
+ typehandlers.add_type_alias('ns3::RngSeedManager', 'ns3::SeedManager')
+ typehandlers.add_type_alias('ns3::RngSeedManager*', 'ns3::SeedManager*')
+ typehandlers.add_type_alias('ns3::RngSeedManager&', 'ns3::SeedManager&')
+ module.add_typedef(root_module['ns3::RngSeedManager'], 'SeedManager')
typehandlers.add_type_alias('void ( * ) ( std::ostream & ) *', 'ns3::LogNodePrinter')
typehandlers.add_type_alias('void ( * ) ( std::ostream & ) **', 'ns3::LogNodePrinter*')
typehandlers.add_type_alias('void ( * ) ( std::ostream & ) *&', 'ns3::LogNodePrinter&')
@@ -371,8 +407,8 @@
register_Ns3ObjectDeleter_methods(root_module, root_module['ns3::ObjectDeleter'])
register_Ns3ObjectFactory_methods(root_module, root_module['ns3::ObjectFactory'])
register_Ns3RandomVariable_methods(root_module, root_module['ns3::RandomVariable'])
+ register_Ns3RngSeedManager_methods(root_module, root_module['ns3::RngSeedManager'])
register_Ns3RngStream_methods(root_module, root_module['ns3::RngStream'])
- register_Ns3SeedManager_methods(root_module, root_module['ns3::SeedManager'])
register_Ns3SequentialVariable_methods(root_module, root_module['ns3::SequentialVariable'])
register_Ns3SimpleRefCount__Ns3Object_Ns3ObjectBase_Ns3ObjectDeleter_methods(root_module, root_module['ns3::SimpleRefCount< ns3::Object, ns3::ObjectBase, ns3::ObjectDeleter >'])
register_Ns3Simulator_methods(root_module, root_module['ns3::Simulator'])
@@ -406,9 +442,11 @@
register_Ns3Object_methods(root_module, root_module['ns3::Object'])
register_Ns3ObjectAggregateIterator_methods(root_module, root_module['ns3::Object::AggregateIterator'])
register_Ns3ParetoVariable_methods(root_module, root_module['ns3::ParetoVariable'])
+ register_Ns3RandomVariableStream_methods(root_module, root_module['ns3::RandomVariableStream'])
register_Ns3Scheduler_methods(root_module, root_module['ns3::Scheduler'])
register_Ns3SchedulerEvent_methods(root_module, root_module['ns3::Scheduler::Event'])
register_Ns3SchedulerEventKey_methods(root_module, root_module['ns3::Scheduler::EventKey'])
+ register_Ns3SequentialRandomVariable_methods(root_module, root_module['ns3::SequentialRandomVariable'])
register_Ns3SimpleRefCount__Ns3AttributeAccessor_Ns3Empty_Ns3DefaultDeleter__lt__ns3AttributeAccessor__gt___methods(root_module, root_module['ns3::SimpleRefCount< ns3::AttributeAccessor, ns3::empty, ns3::DefaultDeleter<ns3::AttributeAccessor> >'])
register_Ns3SimpleRefCount__Ns3AttributeChecker_Ns3Empty_Ns3DefaultDeleter__lt__ns3AttributeChecker__gt___methods(root_module, root_module['ns3::SimpleRefCount< ns3::AttributeChecker, ns3::empty, ns3::DefaultDeleter<ns3::AttributeChecker> >'])
register_Ns3SimpleRefCount__Ns3AttributeValue_Ns3Empty_Ns3DefaultDeleter__lt__ns3AttributeValue__gt___methods(root_module, root_module['ns3::SimpleRefCount< ns3::AttributeValue, ns3::empty, ns3::DefaultDeleter<ns3::AttributeValue> >'])
@@ -423,7 +461,12 @@
register_Ns3SystemThread_methods(root_module, root_module['ns3::SystemThread'])
register_Ns3Time_methods(root_module, root_module['ns3::Time'])
register_Ns3TraceSourceAccessor_methods(root_module, root_module['ns3::TraceSourceAccessor'])
+ register_Ns3TriangularRandomVariable_methods(root_module, root_module['ns3::TriangularRandomVariable'])
+ register_Ns3UniformRandomVariable_methods(root_module, root_module['ns3::UniformRandomVariable'])
register_Ns3WallClockSynchronizer_methods(root_module, root_module['ns3::WallClockSynchronizer'])
+ register_Ns3WeibullRandomVariable_methods(root_module, root_module['ns3::WeibullRandomVariable'])
+ register_Ns3ZetaRandomVariable_methods(root_module, root_module['ns3::ZetaRandomVariable'])
+ register_Ns3ZipfRandomVariable_methods(root_module, root_module['ns3::ZipfRandomVariable'])
register_Ns3AttributeAccessor_methods(root_module, root_module['ns3::AttributeAccessor'])
register_Ns3AttributeChecker_methods(root_module, root_module['ns3::AttributeChecker'])
register_Ns3AttributeValue_methods(root_module, root_module['ns3::AttributeValue'])
@@ -433,22 +476,31 @@
register_Ns3CallbackChecker_methods(root_module, root_module['ns3::CallbackChecker'])
register_Ns3CallbackImplBase_methods(root_module, root_module['ns3::CallbackImplBase'])
register_Ns3CallbackValue_methods(root_module, root_module['ns3::CallbackValue'])
+ register_Ns3ConstantRandomVariable_methods(root_module, root_module['ns3::ConstantRandomVariable'])
register_Ns3DefaultSimulatorImpl_methods(root_module, root_module['ns3::DefaultSimulatorImpl'])
+ register_Ns3DeterministicRandomVariable_methods(root_module, root_module['ns3::DeterministicRandomVariable'])
register_Ns3DoubleValue_methods(root_module, root_module['ns3::DoubleValue'])
+ register_Ns3EmpiricalRandomVariable_methods(root_module, root_module['ns3::EmpiricalRandomVariable'])
register_Ns3EmptyAttributeValue_methods(root_module, root_module['ns3::EmptyAttributeValue'])
register_Ns3EnumChecker_methods(root_module, root_module['ns3::EnumChecker'])
register_Ns3EnumValue_methods(root_module, root_module['ns3::EnumValue'])
+ register_Ns3ErlangRandomVariable_methods(root_module, root_module['ns3::ErlangRandomVariable'])
register_Ns3EventImpl_methods(root_module, root_module['ns3::EventImpl'])
+ register_Ns3ExponentialRandomVariable_methods(root_module, root_module['ns3::ExponentialRandomVariable'])
register_Ns3FdReader_methods(root_module, root_module['ns3::FdReader'])
+ register_Ns3GammaRandomVariable_methods(root_module, root_module['ns3::GammaRandomVariable'])
register_Ns3HeapScheduler_methods(root_module, root_module['ns3::HeapScheduler'])
register_Ns3IntegerValue_methods(root_module, root_module['ns3::IntegerValue'])
register_Ns3ListScheduler_methods(root_module, root_module['ns3::ListScheduler'])
+ register_Ns3LogNormalRandomVariable_methods(root_module, root_module['ns3::LogNormalRandomVariable'])
register_Ns3MapScheduler_methods(root_module, root_module['ns3::MapScheduler'])
+ register_Ns3NormalRandomVariable_methods(root_module, root_module['ns3::NormalRandomVariable'])
register_Ns3ObjectFactoryChecker_methods(root_module, root_module['ns3::ObjectFactoryChecker'])
register_Ns3ObjectFactoryValue_methods(root_module, root_module['ns3::ObjectFactoryValue'])
register_Ns3ObjectPtrContainerAccessor_methods(root_module, root_module['ns3::ObjectPtrContainerAccessor'])
register_Ns3ObjectPtrContainerChecker_methods(root_module, root_module['ns3::ObjectPtrContainerChecker'])
register_Ns3ObjectPtrContainerValue_methods(root_module, root_module['ns3::ObjectPtrContainerValue'])
+ register_Ns3ParetoRandomVariable_methods(root_module, root_module['ns3::ParetoRandomVariable'])
register_Ns3PointerChecker_methods(root_module, root_module['ns3::PointerChecker'])
register_Ns3PointerValue_methods(root_module, root_module['ns3::PointerValue'])
register_Ns3RandomVariableChecker_methods(root_module, root_module['ns3::RandomVariableChecker'])
@@ -918,127 +970,47 @@
is_const=True)
return
-def register_Ns3RngStream_methods(root_module, cls):
- ## rng-stream.h (module 'core'): ns3::RngStream::RngStream() [constructor]
+def register_Ns3RngSeedManager_methods(root_module, cls):
+ ## rng-seed-manager.h (module 'core'): ns3::RngSeedManager::RngSeedManager() [constructor]
cls.add_constructor([])
- ## rng-stream.h (module 'core'): ns3::RngStream::RngStream(ns3::RngStream const & arg0) [copy constructor]
- cls.add_constructor([param('ns3::RngStream const &', 'arg0')])
- ## rng-stream.h (module 'core'): void ns3::RngStream::AdvanceState(int32_t e, int32_t c) [member function]
- cls.add_method('AdvanceState',
- 'void',
- [param('int32_t', 'e'), param('int32_t', 'c')])
- ## rng-stream.h (module 'core'): static bool ns3::RngStream::CheckSeed(uint32_t const * seed) [member function]
- cls.add_method('CheckSeed',
- 'bool',
- [param('uint32_t const *', 'seed')],
+ ## rng-seed-manager.h (module 'core'): ns3::RngSeedManager::RngSeedManager(ns3::RngSeedManager const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::RngSeedManager const &', 'arg0')])
+ ## rng-seed-manager.h (module 'core'): static uint64_t ns3::RngSeedManager::GetNextStreamIndex() [member function]
+ cls.add_method('GetNextStreamIndex',
+ 'uint64_t',
+ [],
is_static=True)
- ## rng-stream.h (module 'core'): static bool ns3::RngStream::CheckSeed(uint32_t seed) [member function]
- cls.add_method('CheckSeed',
- 'bool',
- [param('uint32_t', 'seed')],
+ ## rng-seed-manager.h (module 'core'): static uint64_t ns3::RngSeedManager::GetRun() [member function]
+ cls.add_method('GetRun',
+ 'uint64_t',
+ [],
is_static=True)
- ## rng-stream.h (module 'core'): static uint32_t ns3::RngStream::GetPackageRun() [member function]
- cls.add_method('GetPackageRun',
+ ## rng-seed-manager.h (module 'core'): static uint32_t ns3::RngSeedManager::GetSeed() [member function]
+ cls.add_method('GetSeed',
'uint32_t',
[],
is_static=True)
- ## rng-stream.h (module 'core'): static void ns3::RngStream::GetPackageSeed(uint32_t * seed) [member function]
- cls.add_method('GetPackageSeed',
+ ## rng-seed-manager.h (module 'core'): static void ns3::RngSeedManager::SetRun(uint64_t run) [member function]
+ cls.add_method('SetRun',
'void',
- [param('uint32_t *', 'seed')],
+ [param('uint64_t', 'run')],
is_static=True)
- ## rng-stream.h (module 'core'): void ns3::RngStream::GetState(uint32_t * seed) const [member function]
- cls.add_method('GetState',
+ ## rng-seed-manager.h (module 'core'): static void ns3::RngSeedManager::SetSeed(uint32_t seed) [member function]
+ cls.add_method('SetSeed',
'void',
- [param('uint32_t *', 'seed')],
- is_const=True)
- ## rng-stream.h (module 'core'): void ns3::RngStream::IncreasedPrecis(bool incp) [member function]
- cls.add_method('IncreasedPrecis',
- 'void',
- [param('bool', 'incp')])
- ## rng-stream.h (module 'core'): void ns3::RngStream::InitializeStream() [member function]
- cls.add_method('InitializeStream',
- 'void',
- [])
- ## rng-stream.h (module 'core'): int32_t ns3::RngStream::RandInt(int32_t i, int32_t j) [member function]
- cls.add_method('RandInt',
- 'int32_t',
- [param('int32_t', 'i'), param('int32_t', 'j')])
+ [param('uint32_t', 'seed')],
+ is_static=True)
+ return
+
+def register_Ns3RngStream_methods(root_module, cls):
+ ## rng-stream.h (module 'core'): ns3::RngStream::RngStream(uint32_t seed, uint64_t stream, uint64_t substream) [constructor]
+ cls.add_constructor([param('uint32_t', 'seed'), param('uint64_t', 'stream'), param('uint64_t', 'substream')])
+ ## rng-stream.h (module 'core'): ns3::RngStream::RngStream(ns3::RngStream const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::RngStream const &', 'arg0')])
## rng-stream.h (module 'core'): double ns3::RngStream::RandU01() [member function]
cls.add_method('RandU01',
'double',
[])
- ## rng-stream.h (module 'core'): void ns3::RngStream::ResetNextSubstream() [member function]
- cls.add_method('ResetNextSubstream',
- 'void',
- [])
- ## rng-stream.h (module 'core'): void ns3::RngStream::ResetNthSubstream(uint32_t N) [member function]
- cls.add_method('ResetNthSubstream',
- 'void',
- [param('uint32_t', 'N')])
- ## rng-stream.h (module 'core'): void ns3::RngStream::ResetStartStream() [member function]
- cls.add_method('ResetStartStream',
- 'void',
- [])
- ## rng-stream.h (module 'core'): void ns3::RngStream::ResetStartSubstream() [member function]
- cls.add_method('ResetStartSubstream',
- 'void',
- [])
- ## rng-stream.h (module 'core'): void ns3::RngStream::SetAntithetic(bool a) [member function]
- cls.add_method('SetAntithetic',
- 'void',
- [param('bool', 'a')])
- ## rng-stream.h (module 'core'): static void ns3::RngStream::SetPackageRun(uint32_t run) [member function]
- cls.add_method('SetPackageRun',
- 'void',
- [param('uint32_t', 'run')],
- is_static=True)
- ## rng-stream.h (module 'core'): static bool ns3::RngStream::SetPackageSeed(uint32_t seed) [member function]
- cls.add_method('SetPackageSeed',
- 'bool',
- [param('uint32_t', 'seed')],
- is_static=True)
- ## rng-stream.h (module 'core'): static bool ns3::RngStream::SetPackageSeed(uint32_t const * seed) [member function]
- cls.add_method('SetPackageSeed',
- 'bool',
- [param('uint32_t const *', 'seed')],
- is_static=True)
- ## rng-stream.h (module 'core'): bool ns3::RngStream::SetSeeds(uint32_t const * seed) [member function]
- cls.add_method('SetSeeds',
- 'bool',
- [param('uint32_t const *', 'seed')])
- return
-
-def register_Ns3SeedManager_methods(root_module, cls):
- ## random-variable.h (module 'core'): ns3::SeedManager::SeedManager() [constructor]
- cls.add_constructor([])
- ## random-variable.h (module 'core'): ns3::SeedManager::SeedManager(ns3::SeedManager const & arg0) [copy constructor]
- cls.add_constructor([param('ns3::SeedManager const &', 'arg0')])
- ## random-variable.h (module 'core'): static bool ns3::SeedManager::CheckSeed(uint32_t seed) [member function]
- cls.add_method('CheckSeed',
- 'bool',
- [param('uint32_t', 'seed')],
- is_static=True)
- ## random-variable.h (module 'core'): static uint32_t ns3::SeedManager::GetRun() [member function]
- cls.add_method('GetRun',
- 'uint32_t',
- [],
- is_static=True)
- ## random-variable.h (module 'core'): static uint32_t ns3::SeedManager::GetSeed() [member function]
- cls.add_method('GetSeed',
- 'uint32_t',
- [],
- is_static=True)
- ## random-variable.h (module 'core'): static void ns3::SeedManager::SetRun(uint32_t run) [member function]
- cls.add_method('SetRun',
- 'void',
- [param('uint32_t', 'run')],
- is_static=True)
- ## random-variable.h (module 'core'): static void ns3::SeedManager::SetSeed(uint32_t seed) [member function]
- cls.add_method('SetSeed',
- 'void',
- [param('uint32_t', 'seed')],
- is_static=True)
return
def register_Ns3SequentialVariable_methods(root_module, cls):
@@ -1886,6 +1858,49 @@
cls.add_constructor([param('std::pair< double, double >', 'params'), param('double', 'b')])
return
+def register_Ns3RandomVariableStream_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::RandomVariableStream::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::RandomVariableStream::RandomVariableStream() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): void ns3::RandomVariableStream::SetStream(int64_t stream) [member function]
+ cls.add_method('SetStream',
+ 'void',
+ [param('int64_t', 'stream')])
+ ## random-variable-stream.h (module 'core'): int64_t ns3::RandomVariableStream::GetStream() const [member function]
+ cls.add_method('GetStream',
+ 'int64_t',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): void ns3::RandomVariableStream::SetAntithetic(bool isAntithetic) [member function]
+ cls.add_method('SetAntithetic',
+ 'void',
+ [param('bool', 'isAntithetic')])
+ ## random-variable-stream.h (module 'core'): bool ns3::RandomVariableStream::IsAntithetic() const [member function]
+ cls.add_method('IsAntithetic',
+ 'bool',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::RandomVariableStream::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_pure_virtual=True, is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::RandomVariableStream::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_pure_virtual=True, is_virtual=True)
+ ## random-variable-stream.h (module 'core'): ns3::RngStream * ns3::RandomVariableStream::Peek() const [member function]
+ cls.add_method('Peek',
+ 'ns3::RngStream *',
+ [],
+ is_const=True, visibility='protected')
+ return
+
def register_Ns3Scheduler_methods(root_module, cls):
## scheduler.h (module 'core'): ns3::Scheduler::Scheduler() [constructor]
cls.add_constructor([])
@@ -1951,6 +1966,46 @@
cls.add_instance_attribute('m_uid', 'uint32_t', is_const=False)
return
+def register_Ns3SequentialRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::SequentialRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::SequentialRandomVariable::SequentialRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::SequentialRandomVariable::GetMin() const [member function]
+ cls.add_method('GetMin',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::SequentialRandomVariable::GetMax() const [member function]
+ cls.add_method('GetMax',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): ns3::Ptr<ns3::RandomVariableStream> ns3::SequentialRandomVariable::GetIncrement() const [member function]
+ cls.add_method('GetIncrement',
+ 'ns3::Ptr< ns3::RandomVariableStream >',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::SequentialRandomVariable::GetConsecutive() const [member function]
+ cls.add_method('GetConsecutive',
+ 'uint32_t',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::SequentialRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::SequentialRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3SimpleRefCount__Ns3AttributeAccessor_Ns3Empty_Ns3DefaultDeleter__lt__ns3AttributeAccessor__gt___methods(root_module, cls):
## simple-ref-count.h (module 'core'): ns3::SimpleRefCount<ns3::AttributeAccessor, ns3::empty, ns3::DefaultDeleter<ns3::AttributeAccessor> >::SimpleRefCount() [constructor]
cls.add_constructor([])
@@ -2466,6 +2521,87 @@
is_pure_virtual=True, is_const=True, is_virtual=True)
return
+def register_Ns3TriangularRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::TriangularRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::TriangularRandomVariable::TriangularRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::TriangularRandomVariable::GetMean() const [member function]
+ cls.add_method('GetMean',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::TriangularRandomVariable::GetMin() const [member function]
+ cls.add_method('GetMin',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::TriangularRandomVariable::GetMax() const [member function]
+ cls.add_method('GetMax',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::TriangularRandomVariable::GetValue(double mean, double min, double max) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'mean'), param('double', 'min'), param('double', 'max')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::TriangularRandomVariable::GetInteger(uint32_t mean, uint32_t min, uint32_t max) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'mean'), param('uint32_t', 'min'), param('uint32_t', 'max')])
+ ## random-variable-stream.h (module 'core'): double ns3::TriangularRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::TriangularRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
+def register_Ns3UniformRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::UniformRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::UniformRandomVariable::UniformRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::UniformRandomVariable::GetMin() const [member function]
+ cls.add_method('GetMin',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::UniformRandomVariable::GetMax() const [member function]
+ cls.add_method('GetMax',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::UniformRandomVariable::GetValue(double min, double max) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'min'), param('double', 'max')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::UniformRandomVariable::GetInteger(uint32_t min, uint32_t max) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'min'), param('uint32_t', 'max')])
+ ## random-variable-stream.h (module 'core'): double ns3::UniformRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::UniformRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3WallClockSynchronizer_methods(root_module, cls):
## wall-clock-synchronizer.h (module 'core'): ns3::WallClockSynchronizer::WallClockSynchronizer(ns3::WallClockSynchronizer const & arg0) [copy constructor]
cls.add_constructor([param('ns3::WallClockSynchronizer const &', 'arg0')])
@@ -2564,6 +2700,120 @@
visibility='protected')
return
+def register_Ns3WeibullRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::WeibullRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::WeibullRandomVariable::WeibullRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::WeibullRandomVariable::GetScale() const [member function]
+ cls.add_method('GetScale',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::WeibullRandomVariable::GetShape() const [member function]
+ cls.add_method('GetShape',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::WeibullRandomVariable::GetBound() const [member function]
+ cls.add_method('GetBound',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::WeibullRandomVariable::GetValue(double scale, double shape, double bound) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'scale'), param('double', 'shape'), param('double', 'bound')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::WeibullRandomVariable::GetInteger(uint32_t scale, uint32_t shape, uint32_t bound) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'scale'), param('uint32_t', 'shape'), param('uint32_t', 'bound')])
+ ## random-variable-stream.h (module 'core'): double ns3::WeibullRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::WeibullRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
+def register_Ns3ZetaRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::ZetaRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::ZetaRandomVariable::ZetaRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::ZetaRandomVariable::GetAlpha() const [member function]
+ cls.add_method('GetAlpha',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ZetaRandomVariable::GetValue(double alpha) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'alpha')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ZetaRandomVariable::GetInteger(uint32_t alpha) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'alpha')])
+ ## random-variable-stream.h (module 'core'): double ns3::ZetaRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ZetaRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
+def register_Ns3ZipfRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::ZipfRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::ZipfRandomVariable::ZipfRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ZipfRandomVariable::GetN() const [member function]
+ cls.add_method('GetN',
+ 'uint32_t',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ZipfRandomVariable::GetAlpha() const [member function]
+ cls.add_method('GetAlpha',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ZipfRandomVariable::GetValue(uint32_t n, double alpha) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('uint32_t', 'n'), param('double', 'alpha')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ZipfRandomVariable::GetInteger(uint32_t n, uint32_t alpha) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'n'), param('uint32_t', 'alpha')])
+ ## random-variable-stream.h (module 'core'): double ns3::ZipfRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ZipfRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3AttributeAccessor_methods(root_module, cls):
## attribute.h (module 'core'): ns3::AttributeAccessor::AttributeAccessor(ns3::AttributeAccessor const & arg0) [copy constructor]
cls.add_constructor([param('ns3::AttributeAccessor const &', 'arg0')])
@@ -2780,6 +3030,39 @@
[param('ns3::CallbackBase', 'base')])
return
+def register_Ns3ConstantRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::ConstantRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::ConstantRandomVariable::ConstantRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::ConstantRandomVariable::GetConstant() const [member function]
+ cls.add_method('GetConstant',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ConstantRandomVariable::GetValue(double constant) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'constant')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ConstantRandomVariable::GetInteger(uint32_t constant) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'constant')])
+ ## random-variable-stream.h (module 'core'): double ns3::ConstantRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ConstantRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3DefaultSimulatorImpl_methods(root_module, cls):
## default-simulator-impl.h (module 'core'): ns3::DefaultSimulatorImpl::DefaultSimulatorImpl(ns3::DefaultSimulatorImpl const & arg0) [copy constructor]
cls.add_constructor([param('ns3::DefaultSimulatorImpl const &', 'arg0')])
@@ -2887,6 +3170,30 @@
visibility='private', is_virtual=True)
return
+def register_Ns3DeterministicRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::DeterministicRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::DeterministicRandomVariable::DeterministicRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): void ns3::DeterministicRandomVariable::SetValueArray(double * values, uint64_t length) [member function]
+ cls.add_method('SetValueArray',
+ 'void',
+ [param('double *', 'values'), param('uint64_t', 'length')])
+ ## random-variable-stream.h (module 'core'): double ns3::DeterministicRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::DeterministicRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3DoubleValue_methods(root_module, cls):
## double.h (module 'core'): ns3::DoubleValue::DoubleValue() [constructor]
cls.add_constructor([])
@@ -2920,6 +3227,40 @@
[param('double const &', 'value')])
return
+def register_Ns3EmpiricalRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): ns3::EmpiricalRandomVariable::EmpiricalRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): void ns3::EmpiricalRandomVariable::CDF(double v, double c) [member function]
+ cls.add_method('CDF',
+ 'void',
+ [param('double', 'v'), param('double', 'c')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::EmpiricalRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::EmpiricalRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): double ns3::EmpiricalRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): double ns3::EmpiricalRandomVariable::Interpolate(double arg0, double arg1, double arg2, double arg3, double arg4) [member function]
+ cls.add_method('Interpolate',
+ 'double',
+ [param('double', 'arg0'), param('double', 'arg1'), param('double', 'arg2'), param('double', 'arg3'), param('double', 'arg4')],
+ visibility='private', is_virtual=True)
+ ## random-variable-stream.h (module 'core'): void ns3::EmpiricalRandomVariable::Validate() [member function]
+ cls.add_method('Validate',
+ 'void',
+ [],
+ visibility='private', is_virtual=True)
+ return
+
def register_Ns3EmptyAttributeValue_methods(root_module, cls):
## attribute.h (module 'core'): ns3::EmptyAttributeValue::EmptyAttributeValue(ns3::EmptyAttributeValue const & arg0) [copy constructor]
cls.add_constructor([param('ns3::EmptyAttributeValue const &', 'arg0')])
@@ -3020,6 +3361,44 @@
[param('int', 'v')])
return
+def register_Ns3ErlangRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::ErlangRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::ErlangRandomVariable::ErlangRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ErlangRandomVariable::GetK() const [member function]
+ cls.add_method('GetK',
+ 'uint32_t',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ErlangRandomVariable::GetLambda() const [member function]
+ cls.add_method('GetLambda',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ErlangRandomVariable::GetValue(uint32_t k, double lambda) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('uint32_t', 'k'), param('double', 'lambda')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ErlangRandomVariable::GetInteger(uint32_t k, uint32_t lambda) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'k'), param('uint32_t', 'lambda')])
+ ## random-variable-stream.h (module 'core'): double ns3::ErlangRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ErlangRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3EventImpl_methods(root_module, cls):
## event-impl.h (module 'core'): ns3::EventImpl::EventImpl(ns3::EventImpl const & arg0) [copy constructor]
cls.add_constructor([param('ns3::EventImpl const &', 'arg0')])
@@ -3044,6 +3423,44 @@
is_pure_virtual=True, visibility='protected', is_virtual=True)
return
+def register_Ns3ExponentialRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::ExponentialRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::ExponentialRandomVariable::ExponentialRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::ExponentialRandomVariable::GetMean() const [member function]
+ cls.add_method('GetMean',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ExponentialRandomVariable::GetBound() const [member function]
+ cls.add_method('GetBound',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ExponentialRandomVariable::GetValue(double mean, double bound) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'mean'), param('double', 'bound')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ExponentialRandomVariable::GetInteger(uint32_t mean, uint32_t bound) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'mean'), param('uint32_t', 'bound')])
+ ## random-variable-stream.h (module 'core'): double ns3::ExponentialRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ExponentialRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3FdReader_methods(root_module, cls):
## unix-fd-reader.h (module 'core'): ns3::FdReader::FdReader(ns3::FdReader const & arg0) [copy constructor]
cls.add_constructor([param('ns3::FdReader const &', 'arg0')])
@@ -3064,6 +3481,44 @@
is_pure_virtual=True, visibility='protected', is_virtual=True)
return
+def register_Ns3GammaRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::GammaRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::GammaRandomVariable::GammaRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::GammaRandomVariable::GetAlpha() const [member function]
+ cls.add_method('GetAlpha',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::GammaRandomVariable::GetBeta() const [member function]
+ cls.add_method('GetBeta',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::GammaRandomVariable::GetValue(double alpha, double beta) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'alpha'), param('double', 'beta')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::GammaRandomVariable::GetInteger(uint32_t alpha, uint32_t beta) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'alpha'), param('uint32_t', 'beta')])
+ ## random-variable-stream.h (module 'core'): double ns3::GammaRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::GammaRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3HeapScheduler_methods(root_module, cls):
## heap-scheduler.h (module 'core'): ns3::HeapScheduler::HeapScheduler(ns3::HeapScheduler const & arg0) [copy constructor]
cls.add_constructor([param('ns3::HeapScheduler const &', 'arg0')])
@@ -3171,6 +3626,44 @@
is_virtual=True)
return
+def register_Ns3LogNormalRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::LogNormalRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::LogNormalRandomVariable::LogNormalRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::LogNormalRandomVariable::GetMu() const [member function]
+ cls.add_method('GetMu',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::LogNormalRandomVariable::GetSigma() const [member function]
+ cls.add_method('GetSigma',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::LogNormalRandomVariable::GetValue(double mu, double sigma) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'mu'), param('double', 'sigma')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::LogNormalRandomVariable::GetInteger(uint32_t mu, uint32_t sigma) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'mu'), param('uint32_t', 'sigma')])
+ ## random-variable-stream.h (module 'core'): double ns3::LogNormalRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::LogNormalRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3MapScheduler_methods(root_module, cls):
## map-scheduler.h (module 'core'): ns3::MapScheduler::MapScheduler(ns3::MapScheduler const & arg0) [copy constructor]
cls.add_constructor([param('ns3::MapScheduler const &', 'arg0')])
@@ -3208,6 +3701,51 @@
is_virtual=True)
return
+def register_Ns3NormalRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): ns3::NormalRandomVariable::INFINITE_VALUE [variable]
+ cls.add_static_attribute('INFINITE_VALUE', 'double const', is_const=True)
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::NormalRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::NormalRandomVariable::NormalRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::NormalRandomVariable::GetMean() const [member function]
+ cls.add_method('GetMean',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::NormalRandomVariable::GetVariance() const [member function]
+ cls.add_method('GetVariance',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::NormalRandomVariable::GetBound() const [member function]
+ cls.add_method('GetBound',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::NormalRandomVariable::GetValue(double mean, double variance, double bound) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'mean'), param('double', 'variance'), param('double', 'bound')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::NormalRandomVariable::GetInteger(uint32_t mean, uint32_t variance, uint32_t bound) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'mean'), param('uint32_t', 'variance'), param('uint32_t', 'bound')])
+ ## random-variable-stream.h (module 'core'): double ns3::NormalRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::NormalRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3ObjectFactoryChecker_methods(root_module, cls):
## object-factory.h (module 'core'): ns3::ObjectFactoryChecker::ObjectFactoryChecker() [constructor]
cls.add_constructor([])
@@ -3339,6 +3877,49 @@
is_const=True, is_virtual=True)
return
+def register_Ns3ParetoRandomVariable_methods(root_module, cls):
+ ## random-variable-stream.h (module 'core'): static ns3::TypeId ns3::ParetoRandomVariable::GetTypeId() [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_static=True)
+ ## random-variable-stream.h (module 'core'): ns3::ParetoRandomVariable::ParetoRandomVariable() [constructor]
+ cls.add_constructor([])
+ ## random-variable-stream.h (module 'core'): double ns3::ParetoRandomVariable::GetMean() const [member function]
+ cls.add_method('GetMean',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ParetoRandomVariable::GetShape() const [member function]
+ cls.add_method('GetShape',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ParetoRandomVariable::GetBound() const [member function]
+ cls.add_method('GetBound',
+ 'double',
+ [],
+ is_const=True)
+ ## random-variable-stream.h (module 'core'): double ns3::ParetoRandomVariable::GetValue(double mean, double shape, double bound) [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [param('double', 'mean'), param('double', 'shape'), param('double', 'bound')])
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ParetoRandomVariable::GetInteger(uint32_t mean, uint32_t shape, uint32_t bound) [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [param('uint32_t', 'mean'), param('uint32_t', 'shape'), param('uint32_t', 'bound')])
+ ## random-variable-stream.h (module 'core'): double ns3::ParetoRandomVariable::GetValue() [member function]
+ cls.add_method('GetValue',
+ 'double',
+ [],
+ is_virtual=True)
+ ## random-variable-stream.h (module 'core'): uint32_t ns3::ParetoRandomVariable::GetInteger() [member function]
+ cls.add_method('GetInteger',
+ 'uint32_t',
+ [],
+ is_virtual=True)
+ return
+
def register_Ns3PointerChecker_methods(root_module, cls):
## pointer.h (module 'core'): ns3::PointerChecker::PointerChecker() [constructor]
cls.add_constructor([])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/examples/main-random-variable-stream.cc Tue Jul 31 19:18:23 2012 +0200
@@ -0,0 +1,532 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Timo Bingmann
+ *
+ * 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: Timo Bingmann <timo.bingmann@student.kit.edu>
+ */
+#include "ns3/random-variable-stream.h"
+#include "ns3/ptr.h"
+#include "ns3/double.h"
+#include "ns3/string.h"
+#include "ns3/integer.h"
+#include "ns3/gnuplot.h"
+#include <map>
+#include <cmath>
+
+using namespace ns3;
+
+/// Round a double number to the given precision. e.g. dround(0.234, 0.1) = 0.2
+/// and dround(0.257, 0.1) = 0.3
+double dround (double number, double precision)
+{
+ number /= precision;
+ if (number >= 0)
+ number = std::floor (number + 0.5);
+ else
+ number = std::ceil (number - 0.5);
+ number *= precision;
+ return number;
+}
+
+static GnuplotDataset
+Histogramm (Ptr<RandomVariableStream> rndvar, unsigned int probes, double precision, const std::string& title, bool notcontinous = false)
+{
+ typedef std::map<double, unsigned int> histogramm_maptype;
+ histogramm_maptype histogramm;
+
+ for(unsigned int i = 0; i < probes; ++i)
+ {
+ double val = dround ( rndvar->GetValue (), precision );
+
+ ++histogramm[val];
+ }
+
+ Gnuplot2dDataset data;
+ data.SetTitle (title);
+
+ if (notcontinous)
+ {
+ data.SetStyle (Gnuplot2dDataset::IMPULSES);
+ }
+
+ for(histogramm_maptype::const_iterator hi = histogramm.begin ();
+ hi != histogramm.end (); ++hi)
+ {
+ data.Add (hi->first, (double)hi->second / (double)probes / precision);
+ }
+
+ return data;
+}
+
+int main (int argc, char *argv[])
+{
+ unsigned int probes = 1000000;
+ double precision = 0.01;
+
+ GnuplotCollection gnuplots ("main-random-variables.pdf");
+ gnuplots.SetTerminal ("pdf enhanced");
+
+ {
+ Gnuplot plot;
+ plot.SetTitle ("UniformRandomVariable");
+ plot.AppendExtra ("set yrange [0:]");
+
+ Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable> ();
+ x->SetAttribute ("Min", DoubleValue (0.0));
+ x->SetAttribute ("Max", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x, probes, precision,
+ "UniformRandomVariable [0.0 .. 1.0)") );
+ plot.AddDataset ( Gnuplot2dFunction ("1.0",
+ "0 <= x && x <= 1 ? 1.0 : 0") );
+
+ gnuplots.AddPlot (plot);
+ }
+
+ {
+ Gnuplot plot;
+ plot.SetTitle ("ExponentialRandomVariable");
+ plot.AppendExtra ("set xrange [0:8]");
+ plot.AppendExtra ("ExpDist(x,l) = 1/l * exp(-1/l * x)");
+
+ Ptr<ExponentialRandomVariable> x1 = CreateObject<ExponentialRandomVariable> ();
+ x1->SetAttribute ("Mean", DoubleValue (0.5));
+
+ plot.AddDataset ( Histogramm (x1, probes, precision,
+ "ExponentialRandomVariable m=0.5") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("ExponentialDistribution mean 0.5",
+ "ExpDist(x, 0.5)") );
+
+ Ptr<ExponentialRandomVariable> x2 = CreateObject<ExponentialRandomVariable> ();
+ x2->SetAttribute ("Mean", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x2, probes, precision,
+ "ExponentialRandomVariable m=1") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("ExponentialDistribution mean 1.0",
+ "ExpDist(x, 1.0)") );
+
+ Ptr<ExponentialRandomVariable> x3 = CreateObject<ExponentialRandomVariable> ();
+ x3->SetAttribute ("Mean", DoubleValue (1.5));
+
+ plot.AddDataset ( Histogramm (x3, probes, precision,
+ "ExponentialRandomVariable m=1.5") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("ExponentialDistribution mean 1.5",
+ "ExpDist(x, 1.5)") );
+
+ gnuplots.AddPlot (plot);
+ }
+
+ {
+ Gnuplot plot;
+ plot.SetTitle ("ParetoRandomVariable");
+ plot.AppendExtra ("set xrange [0:2]");
+
+ Ptr<ParetoRandomVariable> x1 = CreateObject<ParetoRandomVariable> ();
+ x1->SetAttribute ("Mean", DoubleValue (1.0));
+ x1->SetAttribute ("Shape", DoubleValue (1.5));
+
+ plot.AddDataset ( Histogramm (x1, probes, precision,
+ "ParetoRandomVariable m=1.0 s=1.5") );
+
+ Ptr<ParetoRandomVariable> x2 = CreateObject<ParetoRandomVariable> ();
+ x2->SetAttribute ("Mean", DoubleValue (1.0));
+ x2->SetAttribute ("Shape", DoubleValue (2.0));
+
+ plot.AddDataset ( Histogramm (x2, probes, precision,
+ "ParetoRandomVariable m=1.0 s=2.0") );
+
+ Ptr<ParetoRandomVariable> x3 = CreateObject<ParetoRandomVariable> ();
+ x3->SetAttribute ("Mean", DoubleValue (1.0));
+ x3->SetAttribute ("Shape", DoubleValue (2.5));
+
+ plot.AddDataset ( Histogramm (x3, probes, precision,
+ "ParetoRandomVariable m=1.0 s=2.5") );
+
+ gnuplots.AddPlot (plot);
+ }
+
+ {
+ Gnuplot plot;
+ plot.SetTitle ("WeibullRandomVariable");
+ plot.AppendExtra ("set xrange [0:3]");
+
+ Ptr<WeibullRandomVariable> x1 = CreateObject<WeibullRandomVariable> ();
+ x1->SetAttribute ("Scale", DoubleValue (1.0));
+ x1->SetAttribute ("Shape", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x1, probes, precision,
+ "WeibullRandomVariable m=1.0 s=1.0") );
+
+ Ptr<WeibullRandomVariable> x2 = CreateObject<WeibullRandomVariable> ();
+ x2->SetAttribute ("Scale", DoubleValue (1.0));
+ x2->SetAttribute ("Shape", DoubleValue (2.0));
+
+ plot.AddDataset ( Histogramm (x2, probes, precision,
+ "WeibullRandomVariable m=1.0 s=2.0") );
+
+ Ptr<WeibullRandomVariable> x3 = CreateObject<WeibullRandomVariable> ();
+ x3->SetAttribute ("Scale", DoubleValue (1.0));
+ x3->SetAttribute ("Shape", DoubleValue (3.0));
+
+ plot.AddDataset ( Histogramm (x3, probes, precision,
+ "WeibullRandomVariable m=1.0 s=3.0") );
+
+ gnuplots.AddPlot (plot);
+ }
+
+ {
+ Gnuplot plot;
+ plot.SetTitle ("NormalRandomVariable");
+ plot.AppendExtra ("set xrange [-3:3]");
+ plot.AppendExtra ("NormalDist(x,m,s) = 1 / (s * sqrt(2*pi)) * exp(-1.0 / 2.0 * ((x-m) / s)**2)");
+
+ Ptr<NormalRandomVariable> x1 = CreateObject<NormalRandomVariable> ();
+ x1->SetAttribute ("Mean", DoubleValue (0.0));
+ x1->SetAttribute ("Variance", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x1, probes, precision,
+ "NormalRandomVariable m=0.0 v=1.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("NormalDist {/Symbol m}=0.0 {/Symbol s}=1.0",
+ "NormalDist(x,0.0,1.0)") );
+
+ Ptr<NormalRandomVariable> x2 = CreateObject<NormalRandomVariable> ();
+ x2->SetAttribute ("Mean", DoubleValue (0.0));
+ x2->SetAttribute ("Variance", DoubleValue (2.0));
+
+ plot.AddDataset ( Histogramm (x2, probes, precision,
+ "NormalRandomVariable m=0.0 v=2.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("NormalDist {/Symbol m}=0.0 {/Symbol s}=sqrt(2.0)",
+ "NormalDist(x,0.0,sqrt(2.0))") );
+
+ Ptr<NormalRandomVariable> x3 = CreateObject<NormalRandomVariable> ();
+ x3->SetAttribute ("Mean", DoubleValue (0.0));
+ x3->SetAttribute ("Variance", DoubleValue (3.0));
+
+ plot.AddDataset ( Histogramm (x3, probes, precision,
+ "NormalRandomVariable m=0.0 v=3.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("NormalDist {/Symbol m}=0.0 {/Symbol s}=sqrt(3.0)",
+ "NormalDist(x,0.0,sqrt(3.0))") );
+
+ gnuplots.AddPlot (plot);
+ }
+
+ // XXX Turn this plot back on once its distribution has been finished.
+ /*
+ {
+ Gnuplot plot;
+ plot.SetTitle ("EmpiricalRandomVariable");
+ plot.AppendExtra ("set xrange [*:*]");
+
+ EmpiricalRandomVariable emp1;
+ emp1.CDF (0.0, 0.0 / 15.0);
+ emp1.CDF (0.2, 1.0 / 15.0);
+ emp1.CDF (0.4, 3.0 / 15.0);
+ emp1.CDF (0.6, 6.0 / 15.0);
+ emp1.CDF (0.8, 10.0 / 15.0);
+ emp1.CDF (1.0, 15.0 / 15.0);
+
+ plot.AddDataset ( Histogramm (emp1, probes, precision,
+ "EmpiricalRandomVariable (Stairs)") );
+
+ gnuplots.AddPlot (plot);
+ }
+ // XXX Turn the above plot back on once its distribution has been finished.
+ */
+
+ // XXX Turn this plot back on once its distribution has been finished.
+ /*
+ {
+ Gnuplot plot;
+ plot.SetTitle ("DeterministicRandomVariable");
+ plot.AppendExtra ("set xrange [*:*]");
+
+ double values[] = { 0.0, 0.2, 0.2, 0.4, 0.2, 0.6, 0.8, 0.8, 1.0 };
+ DeterministicRandomVariable det1 (values, sizeof(values) / sizeof(values[0]));
+
+ plot.AddDataset ( Histogramm (det1, probes, precision,
+ "DeterministicRandomVariable", true) );
+
+ gnuplots.AddPlot (plot);
+ }
+ // XXX Turn the above plot back on once its distribution has been finished.
+ */
+
+ {
+ Gnuplot plot;
+ plot.SetTitle ("LogNormalRandomVariable");
+ plot.AppendExtra ("set xrange [0:3]");
+
+ plot.AppendExtra ("LogNormalDist(x,m,s) = 1.0/x * NormalDist(log(x), m, s)");
+
+ Ptr<LogNormalRandomVariable> x1 = CreateObject<LogNormalRandomVariable> ();
+ x1->SetAttribute ("Mu", DoubleValue (0.0));
+ x1->SetAttribute ("Sigma", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x1, probes, precision,
+ "LogNormalRandomVariable m=0.0 s=1.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("LogNormalDist(x, 0.0, 1.0)",
+ "LogNormalDist(x, 0.0, 1.0)") );
+
+ Ptr<LogNormalRandomVariable> x2 = CreateObject<LogNormalRandomVariable> ();
+ x2->SetAttribute ("Mu", DoubleValue (0.0));
+ x2->SetAttribute ("Sigma", DoubleValue (0.5));
+
+ plot.AddDataset ( Histogramm (x2, probes, precision,
+ "LogNormalRandomVariable m=0.0 s=0.5") );
+
+ Ptr<LogNormalRandomVariable> x3 = CreateObject<LogNormalRandomVariable> ();
+ x3->SetAttribute ("Mu", DoubleValue (0.0));
+ x3->SetAttribute ("Sigma", DoubleValue (0.25));
+
+ plot.AddDataset ( Histogramm (x3, probes, precision,
+ "LogNormalRandomVariable m=0.0 s=0.25") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("LogNormalDist(x, 0.0, 0.25)",
+ "LogNormalDist(x, 0.0, 0.25)") );
+
+ Ptr<LogNormalRandomVariable> x4 = CreateObject<LogNormalRandomVariable> ();
+ x4->SetAttribute ("Mu", DoubleValue (0.0));
+ x4->SetAttribute ("Sigma", DoubleValue (0.125));
+
+ plot.AddDataset ( Histogramm (x4, probes, precision,
+ "LogNormalRandomVariable m=0.0 s=0.125") );
+
+ Ptr<LogNormalRandomVariable> x5 = CreateObject<LogNormalRandomVariable> ();
+ x5->SetAttribute ("Mu", DoubleValue (0.0));
+ x5->SetAttribute ("Sigma", DoubleValue (2.0));
+
+ plot.AddDataset ( Histogramm (x5, probes, precision,
+ "LogNormalRandomVariable m=0.0 s=2.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("LogNormalDist(x, 0.0, 2.0)",
+ "LogNormalDist(x, 0.0, 2.0)") );
+
+ Ptr<LogNormalRandomVariable> x6 = CreateObject<LogNormalRandomVariable> ();
+ x6->SetAttribute ("Mu", DoubleValue (0.0));
+ x6->SetAttribute ("Sigma", DoubleValue (2.5));
+
+ plot.AddDataset ( Histogramm (x6, probes, precision,
+ "LogNormalRandomVariable m=0.0 s=2.5") );
+
+ gnuplots.AddPlot (plot);
+ }
+
+ {
+ Gnuplot plot;
+ plot.SetTitle ("TriangularRandomVariable");
+ plot.AppendExtra ("set xrange [*:*]");
+
+ Ptr<TriangularRandomVariable> x1 = CreateObject<TriangularRandomVariable> ();
+ x1->SetAttribute ("Min", DoubleValue (0.0));
+ x1->SetAttribute ("Max", DoubleValue (1.0));
+ x1->SetAttribute ("Mean", DoubleValue (0.5));
+
+ plot.AddDataset ( Histogramm (x1, probes, precision,
+ "TriangularRandomVariable [0.0 .. 1.0) m=0.5") );
+
+ Ptr<TriangularRandomVariable> x2 = CreateObject<TriangularRandomVariable> ();
+ x2->SetAttribute ("Min", DoubleValue (0.0));
+ x2->SetAttribute ("Max", DoubleValue (1.0));
+ x2->SetAttribute ("Mean", DoubleValue (0.4));
+
+ plot.AddDataset ( Histogramm (x2, probes, precision,
+ "TriangularRandomVariable [0.0 .. 1.0) m=0.4") );
+
+ Ptr<TriangularRandomVariable> x3 = CreateObject<TriangularRandomVariable> ();
+ x3->SetAttribute ("Min", DoubleValue (0.0));
+ x3->SetAttribute ("Max", DoubleValue (1.0));
+ x3->SetAttribute ("Mean", DoubleValue (0.65));
+
+ plot.AddDataset ( Histogramm (x3, probes, precision,
+ "TriangularRandomVariable [0.0 .. 1.0) m=0.65") );
+
+ gnuplots.AddPlot (plot);
+ }
+
+ {
+ Gnuplot plot;
+ plot.SetTitle ("GammaRandomVariable");
+ plot.AppendExtra ("set xrange [0:10]");
+ plot.AppendExtra ("set yrange [0:1]");
+ plot.AppendExtra ("GammaDist(x,a,b) = x**(a-1) * 1/b**a * exp(-x/b) / gamma(a)");
+
+ plot.AppendExtra ("set label 1 '{/Symbol g}(x,{/Symbol a},{/Symbol b}) = x^{/Symbol a-1} e^{-x {/Symbol b}^{-1}} ( {/Symbol b}^{/Symbol a} {/Symbol G}({/Symbol a}) )^{-1}' at 0.7, 0.9");
+
+ Ptr<GammaRandomVariable> x1 = CreateObject<GammaRandomVariable> ();
+ x1->SetAttribute ("Alpha", DoubleValue (1.0));
+ x1->SetAttribute ("Beta", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x1, probes, precision,
+ "GammaRandomVariable a=1.0 b=1.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("{/Symbol g}(x, 1.0, 1.0)",
+ "GammaDist(x, 1.0, 1.0)") );
+
+ Ptr<GammaRandomVariable> x2 = CreateObject<GammaRandomVariable> ();
+ x2->SetAttribute ("Alpha", DoubleValue (1.5));
+ x2->SetAttribute ("Beta", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x2, probes, precision,
+ "GammaRandomVariable a=1.5 b=1.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("{/Symbol g}(x, 1.5, 1.0)",
+ "GammaDist(x, 1.5, 1.0)") );
+
+ Ptr<GammaRandomVariable> x3 = CreateObject<GammaRandomVariable> ();
+ x3->SetAttribute ("Alpha", DoubleValue (2.0));
+ x3->SetAttribute ("Beta", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x3, probes, precision,
+ "GammaRandomVariable a=2.0 b=1.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("{/Symbol g}(x, 2.0, 1.0)",
+ "GammaDist(x, 2.0, 1.0)") );
+
+ Ptr<GammaRandomVariable> x4 = CreateObject<GammaRandomVariable> ();
+ x4->SetAttribute ("Alpha", DoubleValue (4.0));
+ x4->SetAttribute ("Beta", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x4, probes, precision,
+ "GammaRandomVariable a=4.0 b=1.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("{/Symbol g}(x, 4.0, 1.0)",
+ "GammaDist(x, 4.0, 1.0)") );
+
+ Ptr<GammaRandomVariable> x5 = CreateObject<GammaRandomVariable> ();
+ x5->SetAttribute ("Alpha", DoubleValue (2.0));
+ x5->SetAttribute ("Beta", DoubleValue (2.0));
+
+ plot.AddDataset ( Histogramm (x5, probes, precision,
+ "GammaRandomVariable a=2.0 b=2.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("{/Symbol g}(x, 2.0, 2.0)",
+ "GammaDist(x, 2.0, 2.0)") );
+
+ Ptr<GammaRandomVariable> x6 = CreateObject<GammaRandomVariable> ();
+ x6->SetAttribute ("Alpha", DoubleValue (2.5));
+ x6->SetAttribute ("Beta", DoubleValue (3.0));
+
+ plot.AddDataset ( Histogramm (x6, probes, precision,
+ "GammaRandomVariable a=2.5 b=3.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("{/Symbol g}(x, 2.5, 3.0)",
+ "GammaDist(x, 2.5, 3.0)") );
+
+ Ptr<GammaRandomVariable> x7 = CreateObject<GammaRandomVariable> ();
+ x7->SetAttribute ("Alpha", DoubleValue (2.5));
+ x7->SetAttribute ("Beta", DoubleValue (4.5));
+
+ plot.AddDataset ( Histogramm (x7, probes, precision,
+ "GammaRandomVariable a=2.5 b=4.5") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("{/Symbol g}(x, 2.5, 4.5)",
+ "GammaDist(x, 2.5, 4.5)") );
+
+ gnuplots.AddPlot (plot);
+ }
+
+ {
+ Gnuplot plot;
+ plot.SetTitle ("ErlangRandomVariable");
+ plot.AppendExtra ("set xrange [0:10]");
+ plot.AppendExtra ("ErlangDist(x,k,l) = x**(k-1) * 1/l**k * exp(-x/l) / (k-1)!");
+
+ plot.AppendExtra ("set label 1 'Erlang(x,k,{/Symbol l}) = x^{k-1} e^{-x {/Symbol l}^{-1}} ( {/Symbol l}^k (k-1)! )^{-1}' at 0.7, 0.9");
+
+ Ptr<ErlangRandomVariable> x1 = CreateObject<ErlangRandomVariable> ();
+ x1->SetAttribute ("K", IntegerValue (1));
+ x1->SetAttribute ("Lambda", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x1, probes, precision,
+ "ErlangRandomVariable k=1 {/Symbol l}=1.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("Erlang(x, 1, 1.0)",
+ "ErlangDist(x, 1, 1.0)") );
+
+ Ptr<ErlangRandomVariable> x2 = CreateObject<ErlangRandomVariable> ();
+ x2->SetAttribute ("K", IntegerValue (2));
+ x2->SetAttribute ("Lambda", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x2, probes, precision,
+ "ErlangRandomVariable k=2 {/Symbol l}=1.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("Erlang(x, 2, 1.0)",
+ "ErlangDist(x, 2, 1.0)") );
+
+ Ptr<ErlangRandomVariable> x3 = CreateObject<ErlangRandomVariable> ();
+ x3->SetAttribute ("K", IntegerValue (3));
+ x3->SetAttribute ("Lambda", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x3, probes, precision,
+ "ErlangRandomVariable k=3 {/Symbol l}=1.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("Erlang(x, 3, 1.0)",
+ "ErlangDist(x, 3, 1.0)") );
+
+ Ptr<ErlangRandomVariable> x4 = CreateObject<ErlangRandomVariable> ();
+ x4->SetAttribute ("K", IntegerValue (5));
+ x4->SetAttribute ("Lambda", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x4, probes, precision,
+ "ErlangRandomVariable k=5 {/Symbol l}=1.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("Erlang(x, 5, 1.0)",
+ "ErlangDist(x, 5, 1.0)") );
+
+ Ptr<ErlangRandomVariable> x5 = CreateObject<ErlangRandomVariable> ();
+ x5->SetAttribute ("K", IntegerValue (2));
+ x5->SetAttribute ("Lambda", DoubleValue (2.0));
+
+ plot.AddDataset ( Histogramm (x5, probes, precision,
+ "ErlangRandomVariable k=2 {/Symbol l}=2.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("Erlang(x, 2, 2.0)",
+ "ErlangDist(x, 2, 2.0)") );
+
+ Ptr<ErlangRandomVariable> x6 = CreateObject<ErlangRandomVariable> ();
+ x6->SetAttribute ("K", IntegerValue (2));
+ x6->SetAttribute ("Lambda", DoubleValue (3.0));
+
+ plot.AddDataset ( Histogramm (x6, probes, precision,
+ "ErlangRandomVariable k=2 {/Symbol l}=3.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("Erlang(x, 2, 3.0)",
+ "ErlangDist(x, 2, 3.0)") );
+
+ Ptr<ErlangRandomVariable> x7 = CreateObject<ErlangRandomVariable> ();
+ x7->SetAttribute ("K", IntegerValue (2));
+ x7->SetAttribute ("Lambda", DoubleValue (5.0));
+
+ plot.AddDataset ( Histogramm (x7, probes, precision,
+ "ErlangRandomVariable k=2 {/Symbol l}=5.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("Erlang(x, 2, 5.0)",
+ "ErlangDist(x, 2, 5.0)") );
+
+ gnuplots.AddPlot (plot);
+ }
+
+ gnuplots.GenerateOutput (std::cout);
+
+ return 0;
+}
--- a/src/core/examples/main-random-variable.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/core/examples/main-random-variable.cc Tue Jul 31 19:18:23 2012 +0200
@@ -17,7 +17,11 @@
*
* Author: Timo Bingmann <timo.bingmann@student.kit.edu>
*/
-#include "ns3/random-variable.h"
+#include "ns3/random-variable-stream.h"
+#include "ns3/ptr.h"
+#include "ns3/double.h"
+#include "ns3/string.h"
+#include "ns3/integer.h"
#include "ns3/gnuplot.h"
#include <map>
#include <cmath>
@@ -38,14 +42,14 @@
}
static GnuplotDataset
-Histogramm (RandomVariable rndvar, unsigned int probes, double precision, const std::string& title, bool notcontinous = false)
+Histogramm (Ptr<RandomVariableStream> rndvar, unsigned int probes, double precision, const std::string& title, bool notcontinous = false)
{
typedef std::map<double, unsigned int> histogramm_maptype;
histogramm_maptype histogramm;
for(unsigned int i = 0; i < probes; ++i)
{
- double val = dround ( rndvar.GetValue (), precision );
+ double val = dround ( rndvar->GetValue (), precision );
++histogramm[val];
}
@@ -77,13 +81,16 @@
{
Gnuplot plot;
- plot.SetTitle ("UniformVariable");
+ plot.SetTitle ("UniformRandomVariable");
plot.AppendExtra ("set yrange [0:]");
- plot.AddDataset ( Histogramm (UniformVariable (0.0, 1.0), probes, precision,
- "UniformVariable [0.0 .. 1.0)") );
+ Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable> ();
+ x->SetAttribute ("Min", DoubleValue (0.0));
+ x->SetAttribute ("Max", DoubleValue (1.0));
- plot.AddDataset ( Gnuplot2dFunction ("0.1",
+ plot.AddDataset ( Histogramm (x, probes, precision,
+ "UniformRandomVariable [0.0 .. 1.0)") );
+ plot.AddDataset ( Gnuplot2dFunction ("1.0",
"0 <= x && x <= 1 ? 1.0 : 0") );
gnuplots.AddPlot (plot);
@@ -91,24 +98,33 @@
{
Gnuplot plot;
- plot.SetTitle ("ExponentialVariable");
+ plot.SetTitle ("ExponentialRandomVariable");
plot.AppendExtra ("set xrange [0:8]");
plot.AppendExtra ("ExpDist(x,l) = 1/l * exp(-1/l * x)");
- plot.AddDataset ( Histogramm (ExponentialVariable (0.5), probes, precision,
- "ExponentialVariable m=0.5") );
+ Ptr<ExponentialRandomVariable> x1 = CreateObject<ExponentialRandomVariable> ();
+ x1->SetAttribute ("Mean", DoubleValue (0.5));
+
+ plot.AddDataset ( Histogramm (x1, probes, precision,
+ "ExponentialRandomVariable m=0.5") );
plot.AddDataset ( Gnuplot2dFunction ("ExponentialDistribution mean 0.5",
"ExpDist(x, 0.5)") );
- plot.AddDataset ( Histogramm (ExponentialVariable (1.0), probes, precision,
- "ExponentialVariable m=1") );
+ Ptr<ExponentialRandomVariable> x2 = CreateObject<ExponentialRandomVariable> ();
+ x2->SetAttribute ("Mean", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x2, probes, precision,
+ "ExponentialRandomVariable m=1") );
plot.AddDataset ( Gnuplot2dFunction ("ExponentialDistribution mean 1.0",
"ExpDist(x, 1.0)") );
- plot.AddDataset ( Histogramm (ExponentialVariable (1.5), probes, precision,
- "ExponentialVariable m=1.5") );
+ Ptr<ExponentialRandomVariable> x3 = CreateObject<ExponentialRandomVariable> ();
+ x3->SetAttribute ("Mean", DoubleValue (1.5));
+
+ plot.AddDataset ( Histogramm (x3, probes, precision,
+ "ExponentialRandomVariable m=1.5") );
plot.AddDataset ( Gnuplot2dFunction ("ExponentialDistribution mean 1.5",
"ExpDist(x, 1.5)") );
@@ -118,58 +134,94 @@
{
Gnuplot plot;
- plot.SetTitle ("ParetoVariable");
+ plot.SetTitle ("ParetoRandomVariable");
plot.AppendExtra ("set xrange [0:2]");
- plot.AddDataset ( Histogramm (ParetoVariable (1.0, 1.5), probes, precision,
- "ParetoVariable m=1.0 s=1.5") );
+ Ptr<ParetoRandomVariable> x1 = CreateObject<ParetoRandomVariable> ();
+ x1->SetAttribute ("Mean", DoubleValue (1.0));
+ x1->SetAttribute ("Shape", DoubleValue (1.5));
+
+ plot.AddDataset ( Histogramm (x1, probes, precision,
+ "ParetoRandomVariable m=1.0 s=1.5") );
- plot.AddDataset ( Histogramm (ParetoVariable (1.0, 2.0), probes, precision,
- "ParetoVariable m=1.0 s=2.0") );
+ Ptr<ParetoRandomVariable> x2 = CreateObject<ParetoRandomVariable> ();
+ x2->SetAttribute ("Mean", DoubleValue (1.0));
+ x2->SetAttribute ("Shape", DoubleValue (2.0));
+
+ plot.AddDataset ( Histogramm (x2, probes, precision,
+ "ParetoRandomVariable m=1.0 s=2.0") );
- plot.AddDataset ( Histogramm (ParetoVariable (1.0, 2.5), probes, precision,
- "ParetoVariable m=1.0 s=2.5") );
+ Ptr<ParetoRandomVariable> x3 = CreateObject<ParetoRandomVariable> ();
+ x3->SetAttribute ("Mean", DoubleValue (1.0));
+ x3->SetAttribute ("Shape", DoubleValue (2.5));
+
+ plot.AddDataset ( Histogramm (x3, probes, precision,
+ "ParetoRandomVariable m=1.0 s=2.5") );
gnuplots.AddPlot (plot);
}
{
Gnuplot plot;
- plot.SetTitle ("WeibullVariable");
+ plot.SetTitle ("WeibullRandomVariable");
plot.AppendExtra ("set xrange [0:3]");
- plot.AddDataset ( Histogramm (WeibullVariable (1.0, 1.0), probes, precision,
- "WeibullVariable m=1.0 s=1.0") );
+ Ptr<WeibullRandomVariable> x1 = CreateObject<WeibullRandomVariable> ();
+ x1->SetAttribute ("Scale", DoubleValue (1.0));
+ x1->SetAttribute ("Shape", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x1, probes, precision,
+ "WeibullRandomVariable m=1.0 s=1.0") );
- plot.AddDataset ( Histogramm (WeibullVariable (1.0, 2.0), probes, precision,
- "WeibullVariable m=1.0 s=2.0") );
+ Ptr<WeibullRandomVariable> x2 = CreateObject<WeibullRandomVariable> ();
+ x2->SetAttribute ("Scale", DoubleValue (1.0));
+ x2->SetAttribute ("Shape", DoubleValue (2.0));
+
+ plot.AddDataset ( Histogramm (x2, probes, precision,
+ "WeibullRandomVariable m=1.0 s=2.0") );
- plot.AddDataset ( Histogramm (WeibullVariable (1.0, 3.0), probes, precision,
- "WeibullVariable m=1.0 s=3.0") );
+ Ptr<WeibullRandomVariable> x3 = CreateObject<WeibullRandomVariable> ();
+ x3->SetAttribute ("Scale", DoubleValue (1.0));
+ x3->SetAttribute ("Shape", DoubleValue (3.0));
+
+ plot.AddDataset ( Histogramm (x3, probes, precision,
+ "WeibullRandomVariable m=1.0 s=3.0") );
gnuplots.AddPlot (plot);
}
{
Gnuplot plot;
- plot.SetTitle ("NormalVariable");
+ plot.SetTitle ("NormalRandomVariable");
plot.AppendExtra ("set xrange [-3:3]");
plot.AppendExtra ("NormalDist(x,m,s) = 1 / (s * sqrt(2*pi)) * exp(-1.0 / 2.0 * ((x-m) / s)**2)");
- plot.AddDataset ( Histogramm (NormalVariable (0.0, 1.0), probes, precision,
- "NormalVariable m=0.0 v=1.0") );
+ Ptr<NormalRandomVariable> x1 = CreateObject<NormalRandomVariable> ();
+ x1->SetAttribute ("Mean", DoubleValue (0.0));
+ x1->SetAttribute ("Variance", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x1, probes, precision,
+ "NormalRandomVariable m=0.0 v=1.0") );
plot.AddDataset ( Gnuplot2dFunction ("NormalDist {/Symbol m}=0.0 {/Symbol s}=1.0",
"NormalDist(x,0.0,1.0)") );
- plot.AddDataset ( Histogramm (NormalVariable (0.0, 2.0), probes, precision,
- "NormalVariable m=0.0 v=2.0") );
+ Ptr<NormalRandomVariable> x2 = CreateObject<NormalRandomVariable> ();
+ x2->SetAttribute ("Mean", DoubleValue (0.0));
+ x2->SetAttribute ("Variance", DoubleValue (2.0));
+
+ plot.AddDataset ( Histogramm (x2, probes, precision,
+ "NormalRandomVariable m=0.0 v=2.0") );
plot.AddDataset ( Gnuplot2dFunction ("NormalDist {/Symbol m}=0.0 {/Symbol s}=sqrt(2.0)",
"NormalDist(x,0.0,sqrt(2.0))") );
- plot.AddDataset ( Histogramm (NormalVariable (0.0, 3.0), probes, precision,
- "NormalVariable m=0.0 v=3.0") );
+ Ptr<NormalRandomVariable> x3 = CreateObject<NormalRandomVariable> ();
+ x3->SetAttribute ("Mean", DoubleValue (0.0));
+ x3->SetAttribute ("Variance", DoubleValue (3.0));
+
+ plot.AddDataset ( Histogramm (x3, probes, precision,
+ "NormalRandomVariable m=0.0 v=3.0") );
plot.AddDataset ( Gnuplot2dFunction ("NormalDist {/Symbol m}=0.0 {/Symbol s}=sqrt(3.0)",
"NormalDist(x,0.0,sqrt(3.0))") );
@@ -179,138 +231,207 @@
{
Gnuplot plot;
- plot.SetTitle ("EmpiricalVariable");
+ plot.SetTitle ("EmpiricalRandomVariable");
plot.AppendExtra ("set xrange [*:*]");
- EmpiricalVariable emp1;
- emp1.CDF (0.0, 0.0 / 15.0);
- emp1.CDF (0.2, 1.0 / 15.0);
- emp1.CDF (0.4, 3.0 / 15.0);
- emp1.CDF (0.6, 6.0 / 15.0);
- emp1.CDF (0.8, 10.0 / 15.0);
- emp1.CDF (1.0, 15.0 / 15.0);
+ Ptr<EmpiricalRandomVariable> emp1 = CreateObject<EmpiricalRandomVariable> ();
+ emp1->CDF (0.0, 0.0 / 15.0);
+ emp1->CDF (0.2, 1.0 / 15.0);
+ emp1->CDF (0.4, 3.0 / 15.0);
+ emp1->CDF (0.6, 6.0 / 15.0);
+ emp1->CDF (0.8, 10.0 / 15.0);
+ emp1->CDF (1.0, 15.0 / 15.0);
plot.AddDataset ( Histogramm (emp1, probes, precision,
- "EmpiricalVariable (Stairs)") );
+ "EmpiricalRandomVariable (Stairs)") );
+
+ gnuplots.AddPlot (plot);
+ }
+
+ {
+ Gnuplot plot;
+ plot.SetTitle ("DeterministicRandomVariable");
+ plot.AppendExtra ("set xrange [*:*]");
+
+ double values[] = { 0.0, 0.2, 0.2, 0.4, 0.2, 0.6, 0.8, 0.8, 1.0 };
+
+ Ptr<DeterministicRandomVariable> det1 = CreateObject<DeterministicRandomVariable> ();
+ det1->SetValueArray (values, sizeof(values) / sizeof(values[0]));
+
+ plot.AddDataset ( Histogramm (det1, probes, precision,
+ "DeterministicRandomVariable", true) );
gnuplots.AddPlot (plot);
}
{
Gnuplot plot;
- plot.SetTitle ("DeterministicVariable");
- plot.AppendExtra ("set xrange [*:*]");
+ plot.SetTitle ("LogNormalRandomVariable");
+ plot.AppendExtra ("set xrange [0:3]");
+
+ plot.AppendExtra ("LogNormalDist(x,m,s) = 1.0/x * NormalDist(log(x), m, s)");
+
+ Ptr<LogNormalRandomVariable> x1 = CreateObject<LogNormalRandomVariable> ();
+ x1->SetAttribute ("Mu", DoubleValue (0.0));
+ x1->SetAttribute ("Sigma", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x1, probes, precision,
+ "LogNormalRandomVariable m=0.0 s=1.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("LogNormalDist(x, 0.0, 1.0)",
+ "LogNormalDist(x, 0.0, 1.0)") );
+
+ Ptr<LogNormalRandomVariable> x2 = CreateObject<LogNormalRandomVariable> ();
+ x2->SetAttribute ("Mu", DoubleValue (0.0));
+ x2->SetAttribute ("Sigma", DoubleValue (0.5));
+
+ plot.AddDataset ( Histogramm (x2, probes, precision,
+ "LogNormalRandomVariable m=0.0 s=0.5") );
+
+ Ptr<LogNormalRandomVariable> x3 = CreateObject<LogNormalRandomVariable> ();
+ x3->SetAttribute ("Mu", DoubleValue (0.0));
+ x3->SetAttribute ("Sigma", DoubleValue (0.25));
- double values[] = { 0.0, 0.2, 0.2, 0.4, 0.2, 0.6, 0.8, 0.8, 1.0 };
- DeterministicVariable det1 (values, sizeof(values) / sizeof(values[0]));
+ plot.AddDataset ( Histogramm (x3, probes, precision,
+ "LogNormalRandomVariable m=0.0 s=0.25") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("LogNormalDist(x, 0.0, 0.25)",
+ "LogNormalDist(x, 0.0, 0.25)") );
+
+ Ptr<LogNormalRandomVariable> x4 = CreateObject<LogNormalRandomVariable> ();
+ x4->SetAttribute ("Mu", DoubleValue (0.0));
+ x4->SetAttribute ("Sigma", DoubleValue (0.125));
+
+ plot.AddDataset ( Histogramm (x4, probes, precision,
+ "LogNormalRandomVariable m=0.0 s=0.125") );
- plot.AddDataset ( Histogramm (det1, probes, precision,
- "DeterministicVariable", true) );
+ Ptr<LogNormalRandomVariable> x5 = CreateObject<LogNormalRandomVariable> ();
+ x5->SetAttribute ("Mu", DoubleValue (0.0));
+ x5->SetAttribute ("Sigma", DoubleValue (2.0));
+
+ plot.AddDataset ( Histogramm (x5, probes, precision,
+ "LogNormalRandomVariable m=0.0 s=2.0") );
+
+ plot.AddDataset ( Gnuplot2dFunction ("LogNormalDist(x, 0.0, 2.0)",
+ "LogNormalDist(x, 0.0, 2.0)") );
+
+ Ptr<LogNormalRandomVariable> x6 = CreateObject<LogNormalRandomVariable> ();
+ x6->SetAttribute ("Mu", DoubleValue (0.0));
+ x6->SetAttribute ("Sigma", DoubleValue (2.5));
+
+ plot.AddDataset ( Histogramm (x6, probes, precision,
+ "LogNormalRandomVariable m=0.0 s=2.5") );
gnuplots.AddPlot (plot);
}
{
Gnuplot plot;
- plot.SetTitle ("LogNormalVariable");
- plot.AppendExtra ("set xrange [0:3]");
-
- plot.AppendExtra ("LogNormalDist(x,m,s) = 1.0/x * NormalDist(log(x), m, s)");
+ plot.SetTitle ("TriangularRandomVariable");
+ plot.AppendExtra ("set xrange [*:*]");
- plot.AddDataset ( Histogramm (LogNormalVariable (0.0, 1.0), probes, precision,
- "LogNormalVariable m=0.0 s=1.0") );
+ Ptr<TriangularRandomVariable> x1 = CreateObject<TriangularRandomVariable> ();
+ x1->SetAttribute ("Min", DoubleValue (0.0));
+ x1->SetAttribute ("Max", DoubleValue (1.0));
+ x1->SetAttribute ("Mean", DoubleValue (0.5));
- plot.AddDataset ( Gnuplot2dFunction ("LogNormalDist(x, 0.0, 1.0)",
- "LogNormalDist(x, 0.0, 1.0)") );
-
- plot.AddDataset ( Histogramm (LogNormalVariable (0.0, 0.5), probes, precision,
- "LogNormalVariable m=0.0 s=0.5") );
+ plot.AddDataset ( Histogramm (x1, probes, precision,
+ "TriangularRandomVariable [0.0 .. 1.0) m=0.5") );
- plot.AddDataset ( Histogramm (LogNormalVariable (0.0, 0.25), probes, precision,
- "LogNormalVariable m=0.0 s=0.25") );
+ Ptr<TriangularRandomVariable> x2 = CreateObject<TriangularRandomVariable> ();
+ x2->SetAttribute ("Min", DoubleValue (0.0));
+ x2->SetAttribute ("Max", DoubleValue (1.0));
+ x2->SetAttribute ("Mean", DoubleValue (0.4));
- plot.AddDataset ( Gnuplot2dFunction ("LogNormalDist(x, 0.0, 0.25)",
- "LogNormalDist(x, 0.0, 0.25)") );
-
- plot.AddDataset ( Histogramm (LogNormalVariable (0.0, 0.125), probes, precision,
- "LogNormalVariable m=0.0 s=0.125") );
+ plot.AddDataset ( Histogramm (x2, probes, precision,
+ "TriangularRandomVariable [0.0 .. 1.0) m=0.4") );
- plot.AddDataset ( Histogramm (LogNormalVariable (0.0, 2.0), probes, precision,
- "LogNormalVariable m=0.0 s=2.0") );
+ Ptr<TriangularRandomVariable> x3 = CreateObject<TriangularRandomVariable> ();
+ x3->SetAttribute ("Min", DoubleValue (0.0));
+ x3->SetAttribute ("Max", DoubleValue (1.0));
+ x3->SetAttribute ("Mean", DoubleValue (0.65));
- plot.AddDataset ( Gnuplot2dFunction ("LogNormalDist(x, 0.0, 2.0)",
- "LogNormalDist(x, 0.0, 2.0)") );
-
- plot.AddDataset ( Histogramm (LogNormalVariable (0.0, 2.5), probes, precision,
- "LogNormalVariable m=0.0 s=2.5") );
+ plot.AddDataset ( Histogramm (x3, probes, precision,
+ "TriangularRandomVariable [0.0 .. 1.0) m=0.65") );
gnuplots.AddPlot (plot);
}
{
Gnuplot plot;
- plot.SetTitle ("TriangularVariable");
- plot.AppendExtra ("set xrange [*:*]");
-
- plot.AddDataset ( Histogramm (TriangularVariable (0.0, 1.0, 0.5), probes, precision,
- "TriangularVariable [0.0 .. 1.0) m=0.5") );
-
- plot.AddDataset ( Histogramm (TriangularVariable (0.0, 1.0, 0.4), probes, precision,
- "TriangularVariable [0.0 .. 1.0) m=0.4") );
-
- plot.AddDataset ( Histogramm (TriangularVariable (0.0, 1.0, 0.65), probes, precision,
- "TriangularVariable [0.0 .. 1.0) m=0.65") );
-
- gnuplots.AddPlot (plot);
- }
-
- {
- Gnuplot plot;
- plot.SetTitle ("GammaVariable");
+ plot.SetTitle ("GammaRandomVariable");
plot.AppendExtra ("set xrange [0:10]");
plot.AppendExtra ("set yrange [0:1]");
plot.AppendExtra ("GammaDist(x,a,b) = x**(a-1) * 1/b**a * exp(-x/b) / gamma(a)");
plot.AppendExtra ("set label 1 '{/Symbol g}(x,{/Symbol a},{/Symbol b}) = x^{/Symbol a-1} e^{-x {/Symbol b}^{-1}} ( {/Symbol b}^{/Symbol a} {/Symbol G}({/Symbol a}) )^{-1}' at 0.7, 0.9");
- plot.AddDataset ( Histogramm (GammaVariable (1.0, 1.0), probes, precision,
- "GammaVariable a=1.0 b=1.0") );
+ Ptr<GammaRandomVariable> x1 = CreateObject<GammaRandomVariable> ();
+ x1->SetAttribute ("Alpha", DoubleValue (1.0));
+ x1->SetAttribute ("Beta", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x1, probes, precision,
+ "GammaRandomVariable a=1.0 b=1.0") );
plot.AddDataset ( Gnuplot2dFunction ("{/Symbol g}(x, 1.0, 1.0)",
"GammaDist(x, 1.0, 1.0)") );
- plot.AddDataset ( Histogramm (GammaVariable (1.5, 1.0), probes, precision,
- "GammaVariable a=1.5 b=1.0") );
+ Ptr<GammaRandomVariable> x2 = CreateObject<GammaRandomVariable> ();
+ x2->SetAttribute ("Alpha", DoubleValue (1.5));
+ x2->SetAttribute ("Beta", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x2, probes, precision,
+ "GammaRandomVariable a=1.5 b=1.0") );
plot.AddDataset ( Gnuplot2dFunction ("{/Symbol g}(x, 1.5, 1.0)",
"GammaDist(x, 1.5, 1.0)") );
- plot.AddDataset ( Histogramm (GammaVariable (2.0, 1.0), probes, precision,
- "GammaVariable a=2.0 b=1.0") );
+ Ptr<GammaRandomVariable> x3 = CreateObject<GammaRandomVariable> ();
+ x3->SetAttribute ("Alpha", DoubleValue (2.0));
+ x3->SetAttribute ("Beta", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x3, probes, precision,
+ "GammaRandomVariable a=2.0 b=1.0") );
plot.AddDataset ( Gnuplot2dFunction ("{/Symbol g}(x, 2.0, 1.0)",
"GammaDist(x, 2.0, 1.0)") );
- plot.AddDataset ( Histogramm (GammaVariable (4.0, 1.0), probes, precision,
- "GammaVariable a=4.0 b=1.0") );
+ Ptr<GammaRandomVariable> x4 = CreateObject<GammaRandomVariable> ();
+ x4->SetAttribute ("Alpha", DoubleValue (4.0));
+ x4->SetAttribute ("Beta", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x4, probes, precision,
+ "GammaRandomVariable a=4.0 b=1.0") );
plot.AddDataset ( Gnuplot2dFunction ("{/Symbol g}(x, 4.0, 1.0)",
"GammaDist(x, 4.0, 1.0)") );
- plot.AddDataset ( Histogramm (GammaVariable (2.0, 2.0), probes, precision,
- "GammaVariable a=2.0 b=2.0") );
+ Ptr<GammaRandomVariable> x5 = CreateObject<GammaRandomVariable> ();
+ x5->SetAttribute ("Alpha", DoubleValue (2.0));
+ x5->SetAttribute ("Beta", DoubleValue (2.0));
+
+ plot.AddDataset ( Histogramm (x5, probes, precision,
+ "GammaRandomVariable a=2.0 b=2.0") );
plot.AddDataset ( Gnuplot2dFunction ("{/Symbol g}(x, 2.0, 2.0)",
"GammaDist(x, 2.0, 2.0)") );
- plot.AddDataset ( Histogramm (GammaVariable (2.5, 3.0), probes, precision,
- "GammaVariable a=2.5 b=3.0") );
+ Ptr<GammaRandomVariable> x6 = CreateObject<GammaRandomVariable> ();
+ x6->SetAttribute ("Alpha", DoubleValue (2.5));
+ x6->SetAttribute ("Beta", DoubleValue (3.0));
+
+ plot.AddDataset ( Histogramm (x6, probes, precision,
+ "GammaRandomVariable a=2.5 b=3.0") );
plot.AddDataset ( Gnuplot2dFunction ("{/Symbol g}(x, 2.5, 3.0)",
"GammaDist(x, 2.5, 3.0)") );
- plot.AddDataset ( Histogramm (GammaVariable (2.5, 4.5), probes, precision,
- "GammaVariable a=2.5 b=4.5") );
+ Ptr<GammaRandomVariable> x7 = CreateObject<GammaRandomVariable> ();
+ x7->SetAttribute ("Alpha", DoubleValue (2.5));
+ x7->SetAttribute ("Beta", DoubleValue (4.5));
+
+ plot.AddDataset ( Histogramm (x7, probes, precision,
+ "GammaRandomVariable a=2.5 b=4.5") );
plot.AddDataset ( Gnuplot2dFunction ("{/Symbol g}(x, 2.5, 4.5)",
"GammaDist(x, 2.5, 4.5)") );
@@ -320,50 +441,78 @@
{
Gnuplot plot;
- plot.SetTitle ("ErlangVariable");
+ plot.SetTitle ("ErlangRandomVariable");
plot.AppendExtra ("set xrange [0:10]");
plot.AppendExtra ("ErlangDist(x,k,l) = x**(k-1) * 1/l**k * exp(-x/l) / (k-1)!");
plot.AppendExtra ("set label 1 'Erlang(x,k,{/Symbol l}) = x^{k-1} e^{-x {/Symbol l}^{-1}} ( {/Symbol l}^k (k-1)! )^{-1}' at 0.7, 0.9");
- plot.AddDataset ( Histogramm (ErlangVariable (1, 1.0), probes, precision,
- "ErlangVariable k=1 {/Symbol l}=1.0") );
+ Ptr<ErlangRandomVariable> x1 = CreateObject<ErlangRandomVariable> ();
+ x1->SetAttribute ("K", IntegerValue (1));
+ x1->SetAttribute ("Lambda", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x1, probes, precision,
+ "ErlangRandomVariable k=1 {/Symbol l}=1.0") );
plot.AddDataset ( Gnuplot2dFunction ("Erlang(x, 1, 1.0)",
"ErlangDist(x, 1, 1.0)") );
- plot.AddDataset ( Histogramm (ErlangVariable (2, 1.0), probes, precision,
- "ErlangVariable k=2 {/Symbol l}=1.0") );
+ Ptr<ErlangRandomVariable> x2 = CreateObject<ErlangRandomVariable> ();
+ x2->SetAttribute ("K", IntegerValue (2));
+ x2->SetAttribute ("Lambda", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x2, probes, precision,
+ "ErlangRandomVariable k=2 {/Symbol l}=1.0") );
plot.AddDataset ( Gnuplot2dFunction ("Erlang(x, 2, 1.0)",
"ErlangDist(x, 2, 1.0)") );
- plot.AddDataset ( Histogramm (ErlangVariable (3, 1.0), probes, precision,
- "ErlangVariable k=3 {/Symbol l}=1.0") );
+ Ptr<ErlangRandomVariable> x3 = CreateObject<ErlangRandomVariable> ();
+ x3->SetAttribute ("K", IntegerValue (3));
+ x3->SetAttribute ("Lambda", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x3, probes, precision,
+ "ErlangRandomVariable k=3 {/Symbol l}=1.0") );
plot.AddDataset ( Gnuplot2dFunction ("Erlang(x, 3, 1.0)",
"ErlangDist(x, 3, 1.0)") );
- plot.AddDataset ( Histogramm (ErlangVariable (5, 1.0), probes, precision,
- "ErlangVariable k=5 {/Symbol l}=1.0") );
+ Ptr<ErlangRandomVariable> x4 = CreateObject<ErlangRandomVariable> ();
+ x4->SetAttribute ("K", IntegerValue (5));
+ x4->SetAttribute ("Lambda", DoubleValue (1.0));
+
+ plot.AddDataset ( Histogramm (x4, probes, precision,
+ "ErlangRandomVariable k=5 {/Symbol l}=1.0") );
plot.AddDataset ( Gnuplot2dFunction ("Erlang(x, 5, 1.0)",
"ErlangDist(x, 5, 1.0)") );
- plot.AddDataset ( Histogramm (ErlangVariable (2, 2.0), probes, precision,
- "ErlangVariable k=2 {/Symbol l}=2.0") );
+ Ptr<ErlangRandomVariable> x5 = CreateObject<ErlangRandomVariable> ();
+ x5->SetAttribute ("K", IntegerValue (2));
+ x5->SetAttribute ("Lambda", DoubleValue (2.0));
+
+ plot.AddDataset ( Histogramm (x5, probes, precision,
+ "ErlangRandomVariable k=2 {/Symbol l}=2.0") );
plot.AddDataset ( Gnuplot2dFunction ("Erlang(x, 2, 2.0)",
"ErlangDist(x, 2, 2.0)") );
- plot.AddDataset ( Histogramm (ErlangVariable (2, 3.0), probes, precision,
- "ErlangVariable k=2 {/Symbol l}=3.0") );
+ Ptr<ErlangRandomVariable> x6 = CreateObject<ErlangRandomVariable> ();
+ x6->SetAttribute ("K", IntegerValue (2));
+ x6->SetAttribute ("Lambda", DoubleValue (3.0));
+
+ plot.AddDataset ( Histogramm (x6, probes, precision,
+ "ErlangRandomVariable k=2 {/Symbol l}=3.0") );
plot.AddDataset ( Gnuplot2dFunction ("Erlang(x, 2, 3.0)",
"ErlangDist(x, 2, 3.0)") );
- plot.AddDataset ( Histogramm (ErlangVariable (2, 5.0), probes, precision,
- "ErlangVariable k=2 {/Symbol l}=5.0") );
+ Ptr<ErlangRandomVariable> x7 = CreateObject<ErlangRandomVariable> ();
+ x7->SetAttribute ("K", IntegerValue (2));
+ x7->SetAttribute ("Lambda", DoubleValue (5.0));
+
+ plot.AddDataset ( Histogramm (x7, probes, precision,
+ "ErlangRandomVariable k=2 {/Symbol l}=5.0") );
plot.AddDataset ( Gnuplot2dFunction ("Erlang(x, 2, 5.0)",
"ErlangDist(x, 2, 5.0)") );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/examples/sample-random-variable-stream.cc Tue Jul 31 19:18:23 2012 +0200
@@ -0,0 +1,65 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 University of Washington
+ *
+ * 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
+ */
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/command-line.h"
+#include "ns3/random-variable-stream.h"
+#include <iostream>
+
+using namespace ns3;
+using namespace std;
+
+/*
+ * This program can be run from waf such as "./waf --run sample-random-variable-stream"
+ *
+ * This program is about as simple as possible to display the use of ns-3
+ * to generate random numbers. By default, the uniform random variate that
+ * will be outputted is 0.816532. Because ns-3 uses a fixed seed for the
+ * pseudo-random number generator, this program should always output the
+ * same number. Likewise, ns-3 simulations using random variables will
+ * behave deterministically unless the user changes the RunNumber or the
+ * Seed.
+ *
+ * There are three primary mechanisms to change the seed or run numbers
+ * from their default integer value of 1
+ * 1) Through explicit call of SeedManager::SetSeed () and
+ * SeedManager::SetRun () (commented out below)
+ * 2) Through the passing of command line arguments such as:
+ * "./waf --command-template="%s --RngRun=<value>" --run program-name"
+ * 3) Through the use of the NS_GLOBAL_VALUE environment variable, such as:
+ * "NS_GLOBAL_VALUE="RngRun=<value>" ./waf --run program-name"
+ *
+ * For instance, setting the run number to 3 will change the program output to
+ * 0.775417
+ *
+ * Consult the ns-3 manual for more information about the use of the
+ * random number generator
+ */
+
+int main (int argc, char *argv[])
+{
+ CommandLine cmd;
+ cmd.Parse (argc, argv);
+
+ // SeedManager::SetRun (3);
+
+ Ptr<UniformRandomVariable> uv = CreateObject<UniformRandomVariable> ();
+
+ cout << uv->GetValue () << endl;
+
+}
--- a/src/core/examples/wscript Sun Jul 29 14:29:41 2012 +0200
+++ b/src/core/examples/wscript Tue Jul 31 19:18:23 2012 +0200
@@ -18,10 +18,17 @@
obj = bld.create_ns3_program('main-random-variable', ['core', 'config-store', 'tools'])
obj.source = 'main-random-variable.cc'
+ obj = bld.create_ns3_program('main-random-variable-stream', ['core', 'config-store', 'tools'])
+ obj.source = 'main-random-variable-stream.cc'
+
obj = bld.create_ns3_program('sample-random-variable',
['core'])
obj.source = 'sample-random-variable.cc'
+ obj = bld.create_ns3_program('sample-random-variable-stream',
+ ['core'])
+ obj.source = 'sample-random-variable-stream.cc'
+
if bld.env['ENABLE_THREADING'] and bld.env["ENABLE_REAL_TIME"]:
obj = bld.create_ns3_program('main-test-sync', ['network'])
obj.source = 'main-test-sync.cc'
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/model/random-variable-stream-helper.cc Tue Jul 31 19:18:23 2012 +0200
@@ -0,0 +1,45 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 University of Washington
+ *
+ * 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
+ *
+ */
+#include "random-variable-stream.h"
+#include "random-variable-stream-helper.h"
+#include "config.h"
+#include "pointer.h"
+#include "log.h"
+#include "assert.h"
+
+NS_LOG_COMPONENT_DEFINE ("RandomVariableStreamHelper");
+
+namespace ns3 {
+
+int64_t RandomVariableStreamHelper::AssignStreams (std::string path, int64_t stream)
+{
+ NS_ASSERT (stream >= 0);
+ Config::MatchContainer mc = Config::LookupMatches (path);
+ int64_t i = 0;
+ for (Config::MatchContainer::Iterator mci = mc.Begin (); mci != mc.End (); ++mci, ++i)
+ {
+ PointerValue ptr = mc.Get (i);
+ Ptr<RandomVariableStream> rvs = ptr.Get<RandomVariableStream> ();
+ NS_LOG_DEBUG ("RandomVariableStream found: " << rvs << "; setting stream to " << (stream + i));
+ rvs->SetStream (stream + i);
+ }
+ return i;
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/model/random-variable-stream-helper.h Tue Jul 31 19:18:23 2012 +0200
@@ -0,0 +1,65 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 University of Washington
+ *
+ * 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
+ *
+ */
+#ifndef RANDOM_VARIABLE_STREAM_HELPER_H
+#define RANDOM_VARIABLE_STREAM_HELPER_H
+
+#include <string>
+
+namespace ns3 {
+
+/**
+ * \brief Helper class for static methods involving RandomVariableStream
+ */
+class RandomVariableStreamHelper
+{
+public:
+ /**
+ * This helper method can be used to configure the stream number for
+ * one or more RNG streams. The path passed in should correspond to
+ * an attribute path in the configuration system. It may contain wildcards
+ * and may ultimately match zero, one, or more than one objects.
+ *
+ * The objects to match are of type PointerValue where the underlying
+ * type is of type Ptr<RandomVariableStream>.
+ *
+ * \code
+ * .AddAttribute ("Speed",
+ * "A random variable used to pick the speed of a random waypoint model.",
+ * StringValue("ns3::UniformRandomVariable[Min=0.3|Max=0.7]"),
+ * MakePointerAccessor (&RandomWaypointMobilityModel::m_speed),
+ * MakePointerChecker<RandomVariableStream> ())
+ *
+ * \endcode
+ *
+ * Usage would look (for node 3) like this:
+ * \code
+ * std::string path ("/$ns3::NodeListPriv/NodeList/3/$ns3::Node/$ns3::RandomWaypointMobilityModel/Speed/$ns3::UniformRandomVariable");
+ * int64_t retVal = RandomVariableStreamHelper::AssignStreams (path, 0);
+ * \endcode
+ *
+ * \return The number of streams set
+ * \param path (possibly wildcarded) path to a RandomVariableStream PointerValue
+ * \param stream stream number to set; must be non-negative
+ */
+ static int64_t AssignStreams (std::string path, int64_t stream);
+};
+
+} // namespace ns3
+
+#endif /* RANDOM_VARIABLE_STREAM_HELPER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/model/random-variable-stream.cc Tue Jul 31 19:18:23 2012 +0200
@@ -0,0 +1,1507 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 Georgia Tech Research Corporation
+ * Copyright (c) 2011 Mathieu Lacage
+ *
+ * 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
+ *
+ * Authors: Rajib Bhattacharjea<raj.b@gatech.edu>
+ * Hadi Arbabi<marbabi@cs.odu.edu>
+ * Mathieu Lacage <mathieu.lacage@gmail.com>
+ *
+ * Modified by Mitch Watrous <watrous@u.washington.edu>
+ *
+ */
+#include "random-variable-stream.h"
+#include "assert.h"
+#include "boolean.h"
+#include "double.h"
+#include "integer.h"
+#include "string.h"
+#include "pointer.h"
+#include "log.h"
+#include "rng-stream.h"
+#include "rng-seed-manager.h"
+#include <cmath>
+#include <iostream>
+
+NS_LOG_COMPONENT_DEFINE ("RandomVariableStream");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (RandomVariableStream);
+
+TypeId
+RandomVariableStream::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::RandomVariableStream")
+ .SetParent<Object> ()
+ .AddAttribute("Stream",
+ "The stream number for this RNG stream. -1 means \"allocate a stream automatically\". "
+ "Note that if -1 is set, Get will return -1 so that it is not possible to know which "
+ "value was automatically allocated.",
+ IntegerValue(-1),
+ MakeIntegerAccessor(&RandomVariableStream::SetStream,
+ &RandomVariableStream::GetStream),
+ MakeIntegerChecker<int64_t>())
+ .AddAttribute("Antithetic", "Set this RNG stream to generate antithetic values",
+ BooleanValue (false),
+ MakeBooleanAccessor(&RandomVariableStream::SetAntithetic,
+ &RandomVariableStream::IsAntithetic),
+ MakeBooleanChecker())
+ ;
+ return tid;
+}
+
+RandomVariableStream::RandomVariableStream()
+ : m_rng (0)
+{}
+RandomVariableStream::~RandomVariableStream()
+{
+ delete m_rng;
+}
+
+void
+RandomVariableStream::SetAntithetic(bool isAntithetic)
+{
+ m_isAntithetic = isAntithetic;
+}
+bool
+RandomVariableStream::IsAntithetic(void) const
+{
+ return m_isAntithetic;
+}
+void
+RandomVariableStream::SetStream (int64_t stream)
+{
+ NS_LOG_FUNCTION (this << stream);
+ // negative values are not legal.
+ NS_ASSERT (stream >= -1);
+ delete m_rng;
+ if (stream == -1)
+ {
+ // The first 2^63 streams are reserved for automatic stream
+ // number assignment.
+ uint64_t nextStream = RngSeedManager::GetNextStreamIndex ();
+ NS_ASSERT(nextStream <= ((1ULL)<<63));
+ m_rng = new RngStream (RngSeedManager::GetSeed (),
+ nextStream,
+ RngSeedManager::GetRun ());
+ }
+ else
+ {
+ // The last 2^63 streams are reserved for deterministic stream
+ // number assignment.
+ uint64_t base = ((1ULL)<<63);
+ uint64_t target = base + stream;
+ m_rng = new RngStream (RngSeedManager::GetSeed (),
+ target,
+ RngSeedManager::GetRun ());
+ }
+ m_stream = stream;
+}
+int64_t
+RandomVariableStream::GetStream(void) const
+{
+ return m_stream;
+}
+
+RngStream *
+RandomVariableStream::Peek(void) const
+{
+ return m_rng;
+}
+
+NS_OBJECT_ENSURE_REGISTERED(UniformRandomVariable);
+
+TypeId
+UniformRandomVariable::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::UniformRandomVariable")
+ .SetParent<RandomVariableStream>()
+ .AddConstructor<UniformRandomVariable> ()
+ .AddAttribute("Min", "The lower bound on the values returned by this RNG stream.",
+ DoubleValue(0),
+ MakeDoubleAccessor(&UniformRandomVariable::m_min),
+ MakeDoubleChecker<double>())
+ .AddAttribute("Max", "The upper bound on the values returned by this RNG stream.",
+ DoubleValue(1.0),
+ MakeDoubleAccessor(&UniformRandomVariable::m_max),
+ MakeDoubleChecker<double>())
+ ;
+ return tid;
+}
+UniformRandomVariable::UniformRandomVariable ()
+{
+ // m_min and m_max are initialized after constructor by attributes
+}
+
+double
+UniformRandomVariable::GetMin (void) const
+{
+ return m_min;
+}
+double
+UniformRandomVariable::GetMax (void) const
+{
+ return m_max;
+}
+
+double
+UniformRandomVariable::GetValue (double min, double max)
+{
+ double v = min + Peek ()->RandU01 () * (max - min);
+ if (IsAntithetic ())
+ {
+ v = min + (max - v);
+ }
+ return v;
+}
+uint32_t
+UniformRandomVariable::GetInteger (uint32_t min, uint32_t max)
+{
+ NS_ASSERT (min <= max);
+ return static_cast<uint32_t> ( GetValue (min, max + 1) );
+}
+
+double
+UniformRandomVariable::GetValue (void)
+{
+ return GetValue (m_min, m_max);
+}
+uint32_t
+UniformRandomVariable::GetInteger (void)
+{
+ return (uint32_t)GetValue (m_min, m_max + 1);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(ConstantRandomVariable);
+
+TypeId
+ConstantRandomVariable::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::ConstantRandomVariable")
+ .SetParent<RandomVariableStream>()
+ .AddConstructor<ConstantRandomVariable> ()
+ .AddAttribute("Constant", "The constant value returned by this RNG stream.",
+ DoubleValue(0),
+ MakeDoubleAccessor(&ConstantRandomVariable::m_constant),
+ MakeDoubleChecker<double>())
+ ;
+ return tid;
+}
+ConstantRandomVariable::ConstantRandomVariable ()
+{
+ // m_constant is initialized after constructor by attributes
+}
+
+double
+ConstantRandomVariable::GetConstant (void) const
+{
+ return m_constant;
+}
+
+double
+ConstantRandomVariable::GetValue (double constant)
+{
+ return constant;
+}
+uint32_t
+ConstantRandomVariable::GetInteger (uint32_t constant)
+{
+ return constant;
+}
+
+double
+ConstantRandomVariable::GetValue (void)
+{
+ return GetValue (m_constant);
+}
+uint32_t
+ConstantRandomVariable::GetInteger (void)
+{
+ return (uint32_t)GetValue (m_constant);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(SequentialRandomVariable);
+
+TypeId
+SequentialRandomVariable::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::SequentialRandomVariable")
+ .SetParent<RandomVariableStream>()
+ .AddConstructor<SequentialRandomVariable> ()
+ .AddAttribute("Min", "The first value of the sequence.",
+ DoubleValue(0),
+ MakeDoubleAccessor(&SequentialRandomVariable::m_min),
+ MakeDoubleChecker<double>())
+ .AddAttribute("Max", "One more than the last value of the sequence.",
+ DoubleValue(0),
+ MakeDoubleAccessor(&SequentialRandomVariable::m_max),
+ MakeDoubleChecker<double>())
+ .AddAttribute("Increment", "The sequence random variable increment.",
+ StringValue("ns3::ConstantRandomVariable[Contant=1]"),
+ MakePointerAccessor (&SequentialRandomVariable::m_increment),
+ MakePointerChecker<RandomVariableStream> ())
+ .AddAttribute("Consecutive", "The number of times each member of the sequence is repeated.",
+ IntegerValue(1),
+ MakeIntegerAccessor(&SequentialRandomVariable::m_consecutive),
+ MakeIntegerChecker<uint32_t>());
+ ;
+ return tid;
+}
+SequentialRandomVariable::SequentialRandomVariable ()
+ :
+ m_current (0),
+ m_currentConsecutive (0),
+ m_isCurrentSet (false)
+{
+ // m_min, m_max, m_increment, and m_consecutive are initialized
+ // after constructor by attributes.
+}
+
+double
+SequentialRandomVariable::GetMin (void) const
+{
+ return m_min;
+}
+
+double
+SequentialRandomVariable::GetMax (void) const
+{
+ return m_max;
+}
+
+Ptr<RandomVariableStream>
+SequentialRandomVariable::GetIncrement (void) const
+{
+ return m_increment;
+}
+
+uint32_t
+SequentialRandomVariable::GetConsecutive (void) const
+{
+ return m_consecutive;
+}
+
+double
+SequentialRandomVariable::GetValue (void)
+{
+ // Set the current sequence value if it hasn't been set.
+ if (!m_isCurrentSet)
+ {
+ // Start the sequence at its minimium value.
+ m_current = m_min;
+ m_isCurrentSet = true;
+ }
+
+ // Return a sequential series of values
+ double r = m_current;
+ if (++m_currentConsecutive == m_consecutive)
+ { // Time to advance to next
+ m_currentConsecutive = 0;
+ m_current += m_increment->GetValue ();
+ if (m_current >= m_max)
+ {
+ m_current = m_min + (m_current - m_max);
+ }
+ }
+ return r;
+}
+
+uint32_t
+SequentialRandomVariable::GetInteger (void)
+{
+ return (uint32_t)GetValue ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED(ExponentialRandomVariable);
+
+TypeId
+ExponentialRandomVariable::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::ExponentialRandomVariable")
+ .SetParent<RandomVariableStream>()
+ .AddConstructor<ExponentialRandomVariable> ()
+ .AddAttribute("Mean", "The mean of the values returned by this RNG stream.",
+ DoubleValue(1.0),
+ MakeDoubleAccessor(&ExponentialRandomVariable::m_mean),
+ MakeDoubleChecker<double>())
+ .AddAttribute("Bound", "The upper bound on the values returned by this RNG stream.",
+ DoubleValue(0.0),
+ MakeDoubleAccessor(&ExponentialRandomVariable::m_bound),
+ MakeDoubleChecker<double>())
+ ;
+ return tid;
+}
+ExponentialRandomVariable::ExponentialRandomVariable ()
+{
+ // m_mean and m_bound are initialized after constructor by attributes
+}
+
+double
+ExponentialRandomVariable::GetMean (void) const
+{
+ return m_mean;
+}
+double
+ExponentialRandomVariable::GetBound (void) const
+{
+ return m_bound;
+}
+
+double
+ExponentialRandomVariable::GetValue (double mean, double bound)
+{
+ while (1)
+ {
+ // Get a uniform random variable in [0,1].
+ double v = Peek ()->RandU01 ();
+ if (IsAntithetic ())
+ {
+ v = (1 - v);
+ }
+
+ // Calculate the exponential random variable.
+ double r = -mean*std::log (v);
+
+ // Use this value if it's acceptable.
+ if (bound == 0 || r <= bound)
+ {
+ return r;
+ }
+ }
+}
+uint32_t
+ExponentialRandomVariable::GetInteger (uint32_t mean, uint32_t bound)
+{
+ return static_cast<uint32_t> ( GetValue (mean, bound) );
+}
+
+double
+ExponentialRandomVariable::GetValue (void)
+{
+ return GetValue (m_mean, m_bound);
+}
+uint32_t
+ExponentialRandomVariable::GetInteger (void)
+{
+ return (uint32_t)GetValue (m_mean, m_bound);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(ParetoRandomVariable);
+
+TypeId
+ParetoRandomVariable::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::ParetoRandomVariable")
+ .SetParent<RandomVariableStream>()
+ .AddConstructor<ParetoRandomVariable> ()
+ .AddAttribute("Mean", "The mean parameter for the Pareto distribution returned by this RNG stream.",
+ DoubleValue(1.0),
+ MakeDoubleAccessor(&ParetoRandomVariable::m_mean),
+ MakeDoubleChecker<double>())
+ .AddAttribute("Shape", "The shape parameter for the Pareto distribution returned by this RNG stream.",
+ DoubleValue(2.0),
+ MakeDoubleAccessor(&ParetoRandomVariable::m_shape),
+ MakeDoubleChecker<double>())
+ .AddAttribute("Bound", "The upper bound on the values returned by this RNG stream.",
+ DoubleValue(0.0),
+ MakeDoubleAccessor(&ParetoRandomVariable::m_bound),
+ MakeDoubleChecker<double>())
+ ;
+ return tid;
+}
+ParetoRandomVariable::ParetoRandomVariable ()
+{
+ // m_mean, m_shape, and m_bound are initialized after constructor
+ // by attributes
+}
+
+double
+ParetoRandomVariable::GetMean (void) const
+{
+ return m_mean;
+}
+double
+ParetoRandomVariable::GetShape (void) const
+{
+ return m_shape;
+}
+double
+ParetoRandomVariable::GetBound (void) const
+{
+ return m_bound;
+}
+
+double
+ParetoRandomVariable::GetValue (double mean, double shape, double bound)
+{
+ // Calculate the scale parameter.
+ double scale = mean * (shape - 1.0) / shape;
+
+ while (1)
+ {
+ // Get a uniform random variable in [0,1].
+ double v = Peek ()->RandU01 ();
+ if (IsAntithetic ())
+ {
+ v = (1 - v);
+ }
+
+ // Calculate the Pareto random variable.
+ double r = (scale * ( 1.0 / std::pow (v, 1.0 / shape)));
+
+ // Use this value if it's acceptable.
+ if (bound == 0 || r <= bound)
+ {
+ return r;
+ }
+ }
+}
+uint32_t
+ParetoRandomVariable::GetInteger (uint32_t mean, uint32_t shape, uint32_t bound)
+{
+ return static_cast<uint32_t> ( GetValue (mean, shape, bound) );
+}
+
+double
+ParetoRandomVariable::GetValue (void)
+{
+ return GetValue (m_mean, m_shape, m_bound);
+}
+uint32_t
+ParetoRandomVariable::GetInteger (void)
+{
+ return (uint32_t)GetValue (m_mean, m_shape, m_bound);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(WeibullRandomVariable);
+
+TypeId
+WeibullRandomVariable::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::WeibullRandomVariable")
+ .SetParent<RandomVariableStream>()
+ .AddConstructor<WeibullRandomVariable> ()
+ .AddAttribute("Scale", "The scale parameter for the Weibull distribution returned by this RNG stream.",
+ DoubleValue(1.0),
+ MakeDoubleAccessor(&WeibullRandomVariable::m_scale),
+ MakeDoubleChecker<double>())
+ .AddAttribute("Shape", "The shape parameter for the Weibull distribution returned by this RNG stream.",
+ DoubleValue(1),
+ MakeDoubleAccessor(&WeibullRandomVariable::m_shape),
+ MakeDoubleChecker<double>())
+ .AddAttribute("Bound", "The upper bound on the values returned by this RNG stream.",
+ DoubleValue(0.0),
+ MakeDoubleAccessor(&WeibullRandomVariable::m_bound),
+ MakeDoubleChecker<double>())
+ ;
+ return tid;
+}
+WeibullRandomVariable::WeibullRandomVariable ()
+{
+ // m_scale, m_shape, and m_bound are initialized after constructor
+ // by attributes
+}
+
+double
+WeibullRandomVariable::GetScale (void) const
+{
+ return m_scale;
+}
+double
+WeibullRandomVariable::GetShape (void) const
+{
+ return m_shape;
+}
+double
+WeibullRandomVariable::GetBound (void) const
+{
+ return m_bound;
+}
+
+double
+WeibullRandomVariable::GetValue (double scale, double shape, double bound)
+{
+ double exponent = 1.0 / shape;
+ while (1)
+ {
+ // Get a uniform random variable in [0,1].
+ double v = Peek ()->RandU01 ();
+ if (IsAntithetic ())
+ {
+ v = (1 - v);
+ }
+
+ // Calculate the Weibull random variable.
+ double r = scale * std::pow ( -std::log (v), exponent);
+
+ // Use this value if it's acceptable.
+ if (bound == 0 || r <= bound)
+ {
+ return r;
+ }
+ }
+}
+uint32_t
+WeibullRandomVariable::GetInteger (uint32_t scale, uint32_t shape, uint32_t bound)
+{
+ return static_cast<uint32_t> ( GetValue (scale, shape, bound) );
+}
+
+double
+WeibullRandomVariable::GetValue (void)
+{
+ return GetValue (m_scale, m_shape, m_bound);
+}
+uint32_t
+WeibullRandomVariable::GetInteger (void)
+{
+ return (uint32_t)GetValue (m_scale, m_shape, m_bound);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(NormalRandomVariable);
+
+const double NormalRandomVariable::INFINITE_VALUE = 1e307;
+
+TypeId
+NormalRandomVariable::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::NormalRandomVariable")
+ .SetParent<RandomVariableStream>()
+ .AddConstructor<NormalRandomVariable> ()
+ .AddAttribute("Mean", "The mean value for the normal distribution returned by this RNG stream.",
+ DoubleValue(0.0),
+ MakeDoubleAccessor(&NormalRandomVariable::m_mean),
+ MakeDoubleChecker<double>())
+ .AddAttribute("Variance", "The variance value for the normal distribution returned by this RNG stream.",
+ DoubleValue(1.0),
+ MakeDoubleAccessor(&NormalRandomVariable::m_variance),
+ MakeDoubleChecker<double>())
+ .AddAttribute("Bound", "The bound on the values returned by this RNG stream.",
+ DoubleValue(INFINITE_VALUE),
+ MakeDoubleAccessor(&NormalRandomVariable::m_bound),
+ MakeDoubleChecker<double>())
+ ;
+ return tid;
+}
+NormalRandomVariable::NormalRandomVariable ()
+ :
+ m_nextValid (false)
+{
+ // m_mean, m_variance, and m_bound are initialized after constructor
+ // by attributes
+}
+
+double
+NormalRandomVariable::GetMean (void) const
+{
+ return m_mean;
+}
+double
+NormalRandomVariable::GetVariance (void) const
+{
+ return m_variance;
+}
+double
+NormalRandomVariable::GetBound (void) const
+{
+ return m_bound;
+}
+
+double
+NormalRandomVariable::GetValue (double mean, double variance, double bound)
+{
+ if (m_nextValid)
+ { // use previously generated
+ m_nextValid = false;
+ return m_next;
+ }
+ while (1)
+ { // See Simulation Modeling and Analysis p. 466 (Averill Law)
+ // for algorithm; basically a Box-Muller transform:
+ // http://en.wikipedia.org/wiki/Box-Muller_transform
+ double u1 = Peek ()->RandU01 ();
+ double u2 = Peek ()->RandU01 ();
+ if (IsAntithetic ())
+ {
+ u1 = (1 - u1);
+ u2 = (1 - u2);
+ }
+ double v1 = 2 * u1 - 1;
+ double v2 = 2 * u2 - 1;
+ double w = v1 * v1 + v2 * v2;
+ if (w <= 1.0)
+ { // Got good pair
+ double y = sqrt ((-2 * log (w)) / w);
+ m_next = mean + v2 * y * sqrt (variance);
+ // if next is in bounds, it is valid
+ m_nextValid = fabs (m_next - mean) <= bound;
+ double x1 = mean + v1 * y * sqrt (variance);
+ // if x1 is in bounds, return it
+ if (fabs (x1 - mean) <= bound)
+ {
+ return x1;
+ }
+ // otherwise try and return m_next if it is valid
+ else if (m_nextValid)
+ {
+ m_nextValid = false;
+ return m_next;
+ }
+ // otherwise, just run this loop again
+ }
+ }
+}
+
+uint32_t
+NormalRandomVariable::GetInteger (uint32_t mean, uint32_t variance, uint32_t bound)
+{
+ return static_cast<uint32_t> ( GetValue (mean, variance, bound) );
+}
+
+double
+NormalRandomVariable::GetValue (void)
+{
+ return GetValue (m_mean, m_variance, m_bound);
+}
+uint32_t
+NormalRandomVariable::GetInteger (void)
+{
+ return (uint32_t)GetValue (m_mean, m_variance, m_bound);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(LogNormalRandomVariable);
+
+TypeId
+LogNormalRandomVariable::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::LogNormalRandomVariable")
+ .SetParent<RandomVariableStream>()
+ .AddConstructor<LogNormalRandomVariable> ()
+ .AddAttribute("Mu", "The mu value for the log-normal distribution returned by this RNG stream.",
+ DoubleValue(0.0),
+ MakeDoubleAccessor(&LogNormalRandomVariable::m_mu),
+ MakeDoubleChecker<double>())
+ .AddAttribute("Sigma", "The sigma value for the log-normal distribution returned by this RNG stream.",
+ DoubleValue(1.0),
+ MakeDoubleAccessor(&LogNormalRandomVariable::m_sigma),
+ MakeDoubleChecker<double>())
+ ;
+ return tid;
+}
+LogNormalRandomVariable::LogNormalRandomVariable ()
+{
+ // m_mu and m_sigma are initialized after constructor by
+ // attributes
+}
+
+double
+LogNormalRandomVariable::GetMu (void) const
+{
+ return m_mu;
+}
+double
+LogNormalRandomVariable::GetSigma (void) const
+{
+ return m_sigma;
+}
+
+// The code from this function was adapted from the GNU Scientific
+// Library 1.8:
+/* randist/lognormal.c
+ *
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000 James Theiler, Brian Gough
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+/* The lognormal distribution has the form
+
+ p(x) dx = 1/(x * sqrt(2 pi sigma^2)) exp(-(ln(x) - zeta)^2/2 sigma^2) dx
+
+ for x > 0. Lognormal random numbers are the exponentials of
+ gaussian random numbers */
+double
+LogNormalRandomVariable::GetValue (double mu, double sigma)
+{
+ double v1, v2, r2, normal, x;
+
+ do
+ {
+ /* choose x,y in uniform square (-1,-1) to (+1,+1) */
+
+ double u1 = Peek ()->RandU01 ();
+ double u2 = Peek ()->RandU01 ();
+ if (IsAntithetic ())
+ {
+ u1 = (1 - u1);
+ u2 = (1 - u2);
+ }
+
+ v1 = -1 + 2 * u1;
+ v2 = -1 + 2 * u2;
+
+ /* see if it is in the unit circle */
+ r2 = v1 * v1 + v2 * v2;
+ }
+ while (r2 > 1.0 || r2 == 0);
+
+ normal = v1 * std::sqrt (-2.0 * std::log (r2) / r2);
+
+ x = std::exp (sigma * normal + mu);
+
+ return x;
+}
+
+uint32_t
+LogNormalRandomVariable::GetInteger (uint32_t mu, uint32_t sigma)
+{
+ return static_cast<uint32_t> ( GetValue (mu, sigma));
+}
+
+double
+LogNormalRandomVariable::GetValue (void)
+{
+ return GetValue (m_mu, m_sigma);
+}
+uint32_t
+LogNormalRandomVariable::GetInteger (void)
+{
+ return (uint32_t)GetValue (m_mu, m_sigma);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(GammaRandomVariable);
+
+TypeId
+GammaRandomVariable::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::GammaRandomVariable")
+ .SetParent<RandomVariableStream>()
+ .AddConstructor<GammaRandomVariable> ()
+ .AddAttribute("Alpha", "The alpha value for the gamma distribution returned by this RNG stream.",
+ DoubleValue(1.0),
+ MakeDoubleAccessor(&GammaRandomVariable::m_alpha),
+ MakeDoubleChecker<double>())
+ .AddAttribute("Beta", "The beta value for the gamma distribution returned by this RNG stream.",
+ DoubleValue(1.0),
+ MakeDoubleAccessor(&GammaRandomVariable::m_beta),
+ MakeDoubleChecker<double>())
+ ;
+ return tid;
+}
+GammaRandomVariable::GammaRandomVariable ()
+ :
+ m_nextValid (false)
+{
+ // m_alpha and m_beta are initialized after constructor by
+ // attributes
+}
+
+double
+GammaRandomVariable::GetAlpha (void) const
+{
+ return m_alpha;
+}
+double
+GammaRandomVariable::GetBeta (void) const
+{
+ return m_beta;
+}
+
+/*
+ The code for the following generator functions was adapted from ns-2
+ tools/ranvar.cc
+
+ Originally the algorithm was devised by Marsaglia in 2000:
+ G. Marsaglia, W. W. Tsang: A simple method for gereating Gamma variables
+ ACM Transactions on mathematical software, Vol. 26, No. 3, Sept. 2000
+
+ The Gamma distribution density function has the form
+
+ x^(alpha-1) * exp(-x/beta)
+ p(x; alpha, beta) = ----------------------------
+ beta^alpha * Gamma(alpha)
+
+ for x > 0.
+*/
+double
+GammaRandomVariable::GetValue (double alpha, double beta)
+{
+ if (alpha < 1)
+ {
+ double u = Peek ()->RandU01 ();
+ if (IsAntithetic ())
+ {
+ u = (1 - u);
+ }
+ return GetValue (1.0 + alpha, beta) * std::pow (u, 1.0 / alpha);
+ }
+
+ double x, v, u;
+ double d = alpha - 1.0 / 3.0;
+ double c = (1.0 / 3.0) / sqrt (d);
+
+ while (1)
+ {
+ do
+ {
+ // Get a value from a normal distribution that has mean
+ // zero, variance 1, and no bound.
+ double mean = 0.0;
+ double variance = 1.0;
+ double bound = NormalRandomVariable::INFINITE_VALUE;
+ x = GetNormalValue (mean, variance, bound);
+
+ v = 1.0 + c * x;
+ }
+ while (v <= 0);
+
+ v = v * v * v;
+ u = Peek ()->RandU01 ();
+ if (IsAntithetic ())
+ {
+ u = (1 - u);
+ }
+ if (u < 1 - 0.0331 * x * x * x * x)
+ {
+ break;
+ }
+ if (log (u) < 0.5 * x * x + d * (1 - v + log (v)))
+ {
+ break;
+ }
+ }
+
+ return beta * d * v;
+}
+
+uint32_t
+GammaRandomVariable::GetInteger (uint32_t alpha, uint32_t beta)
+{
+ return static_cast<uint32_t> ( GetValue (alpha, beta));
+}
+
+double
+GammaRandomVariable::GetValue (void)
+{
+ return GetValue (m_alpha, m_beta);
+}
+uint32_t
+GammaRandomVariable::GetInteger (void)
+{
+ return (uint32_t)GetValue (m_alpha, m_beta);
+}
+
+double
+GammaRandomVariable::GetNormalValue (double mean, double variance, double bound)
+{
+ if (m_nextValid)
+ { // use previously generated
+ m_nextValid = false;
+ return m_next;
+ }
+ while (1)
+ { // See Simulation Modeling and Analysis p. 466 (Averill Law)
+ // for algorithm; basically a Box-Muller transform:
+ // http://en.wikipedia.org/wiki/Box-Muller_transform
+ double u1 = Peek ()->RandU01 ();
+ double u2 = Peek ()->RandU01 ();
+ if (IsAntithetic ())
+ {
+ u1 = (1 - u1);
+ u2 = (1 - u2);
+ }
+ double v1 = 2 * u1 - 1;
+ double v2 = 2 * u2 - 1;
+ double w = v1 * v1 + v2 * v2;
+ if (w <= 1.0)
+ { // Got good pair
+ double y = sqrt ((-2 * log (w)) / w);
+ m_next = mean + v2 * y * sqrt (variance);
+ // if next is in bounds, it is valid
+ m_nextValid = fabs (m_next - mean) <= bound;
+ double x1 = mean + v1 * y * sqrt (variance);
+ // if x1 is in bounds, return it
+ if (fabs (x1 - mean) <= bound)
+ {
+ return x1;
+ }
+ // otherwise try and return m_next if it is valid
+ else if (m_nextValid)
+ {
+ m_nextValid = false;
+ return m_next;
+ }
+ // otherwise, just run this loop again
+ }
+ }
+}
+
+NS_OBJECT_ENSURE_REGISTERED(ErlangRandomVariable);
+
+TypeId
+ErlangRandomVariable::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::ErlangRandomVariable")
+ .SetParent<RandomVariableStream>()
+ .AddConstructor<ErlangRandomVariable> ()
+ .AddAttribute("K", "The k value for the Erlang distribution returned by this RNG stream.",
+ IntegerValue(1),
+ MakeIntegerAccessor(&ErlangRandomVariable::m_k),
+ MakeIntegerChecker<uint32_t>())
+ .AddAttribute("Lambda", "The lambda value for the Erlang distribution returned by this RNG stream.",
+ DoubleValue(1.0),
+ MakeDoubleAccessor(&ErlangRandomVariable::m_lambda),
+ MakeDoubleChecker<double>())
+ ;
+ return tid;
+}
+ErlangRandomVariable::ErlangRandomVariable ()
+{
+ // m_k and m_lambda are initialized after constructor by attributes
+}
+
+uint32_t
+ErlangRandomVariable::GetK (void) const
+{
+ return m_k;
+}
+double
+ErlangRandomVariable::GetLambda (void) const
+{
+ return m_lambda;
+}
+
+/*
+ The code for the following generator functions was adapted from ns-2
+ tools/ranvar.cc
+
+ The Erlang distribution density function has the form
+
+ x^(k-1) * exp(-x/lambda)
+ p(x; k, lambda) = ---------------------------
+ lambda^k * (k-1)!
+
+ for x > 0.
+*/
+double
+ErlangRandomVariable::GetValue (uint32_t k, double lambda)
+{
+ double mean = lambda;
+ double bound = 0.0;
+
+ double result = 0;
+ for (unsigned int i = 0; i < k; ++i)
+ {
+ result += GetExponentialValue (mean, bound);
+
+ }
+
+ return result;
+}
+
+uint32_t
+ErlangRandomVariable::GetInteger (uint32_t k, uint32_t lambda)
+{
+ return static_cast<uint32_t> ( GetValue (k, lambda));
+}
+
+double
+ErlangRandomVariable::GetValue (void)
+{
+ return GetValue (m_k, m_lambda);
+}
+uint32_t
+ErlangRandomVariable::GetInteger (void)
+{
+ return (uint32_t)GetValue (m_k, m_lambda);
+}
+
+double
+ErlangRandomVariable::GetExponentialValue (double mean, double bound)
+{
+ while (1)
+ {
+ // Get a uniform random variable in [0,1].
+ double v = Peek ()->RandU01 ();
+ if (IsAntithetic ())
+ {
+ v = (1 - v);
+ }
+
+ // Calculate the exponential random variable.
+ double r = -mean*std::log (v);
+
+ // Use this value if it's acceptable.
+ if (bound == 0 || r <= bound)
+ {
+ return r;
+ }
+ }
+}
+
+NS_OBJECT_ENSURE_REGISTERED(TriangularRandomVariable);
+
+TypeId
+TriangularRandomVariable::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::TriangularRandomVariable")
+ .SetParent<RandomVariableStream>()
+ .AddConstructor<TriangularRandomVariable> ()
+ .AddAttribute("Mean", "The mean value for the triangular distribution returned by this RNG stream.",
+ DoubleValue(0.5),
+ MakeDoubleAccessor(&TriangularRandomVariable::m_mean),
+ MakeDoubleChecker<double>())
+ .AddAttribute("Min", "The lower bound on the values returned by this RNG stream.",
+ DoubleValue(0.0),
+ MakeDoubleAccessor(&TriangularRandomVariable::m_min),
+ MakeDoubleChecker<double>())
+ .AddAttribute("Max", "The upper bound on the values returned by this RNG stream.",
+ DoubleValue(1.0),
+ MakeDoubleAccessor(&TriangularRandomVariable::m_max),
+ MakeDoubleChecker<double>())
+ ;
+ return tid;
+}
+TriangularRandomVariable::TriangularRandomVariable ()
+ :
+ m_mode (0.5)
+{
+ // m_mean, m_min, and m_max are initialized after constructor by
+ // attributes
+}
+
+double
+TriangularRandomVariable::GetMean (void) const
+{
+ return m_mean;
+}
+double
+TriangularRandomVariable::GetMin (void) const
+{
+ return m_min;
+}
+double
+TriangularRandomVariable::GetMax (void) const
+{
+ return m_max;
+}
+
+double
+TriangularRandomVariable::GetValue (double mean, double min, double max)
+{
+ // Calculate the mode.
+ double mode = 3.0 * mean - min - max;
+
+ // Get a uniform random variable in [0,1].
+ double u = Peek ()->RandU01 ();
+ if (IsAntithetic ())
+ {
+ u = (1 - u);
+ }
+
+ // Calculate the triangular random variable.
+ if (u <= (mode - min) / (max - min) )
+ {
+ return min + sqrt (u * (max - min) * (mode - min) );
+ }
+ else
+ {
+ return max - sqrt ( (1 - u) * (max - min) * (max - mode) );
+ }
+}
+
+uint32_t
+TriangularRandomVariable::GetInteger (uint32_t mean, uint32_t min, uint32_t max)
+{
+ return static_cast<uint32_t> ( GetValue (mean, min, max) );
+}
+
+double
+TriangularRandomVariable::GetValue (void)
+{
+ return GetValue (m_mean, m_min, m_max);
+}
+uint32_t
+TriangularRandomVariable::GetInteger (void)
+{
+ return (uint32_t)GetValue (m_mean, m_min, m_max);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(ZipfRandomVariable);
+
+TypeId
+ZipfRandomVariable::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::ZipfRandomVariable")
+ .SetParent<RandomVariableStream>()
+ .AddConstructor<ZipfRandomVariable> ()
+ .AddAttribute("N", "The n value for the Zipf distribution returned by this RNG stream.",
+ IntegerValue(1),
+ MakeIntegerAccessor(&ZipfRandomVariable::m_n),
+ MakeIntegerChecker<uint32_t>())
+ .AddAttribute("Alpha", "The alpha value for the Zipf distribution returned by this RNG stream.",
+ DoubleValue(0.0),
+ MakeDoubleAccessor(&ZipfRandomVariable::m_alpha),
+ MakeDoubleChecker<double>())
+ ;
+ return tid;
+}
+ZipfRandomVariable::ZipfRandomVariable ()
+{
+ // m_n and m_alpha are initialized after constructor by attributes
+}
+
+uint32_t
+ZipfRandomVariable::GetN (void) const
+{
+ return m_n;
+}
+double
+ZipfRandomVariable::GetAlpha (void) const
+{
+ return m_alpha;
+}
+
+double
+ZipfRandomVariable::GetValue (uint32_t n, double alpha)
+{
+ // Calculate the normalization constant c.
+ m_c = 0.0;
+ for (uint32_t i = 1; i <= n; i++)
+ {
+ m_c += (1.0 / std::pow ((double)i,alpha));
+ }
+ m_c = 1.0 / m_c;
+
+ // Get a uniform random variable in [0,1].
+ double u = Peek ()->RandU01 ();
+ if (IsAntithetic ())
+ {
+ u = (1 - u);
+ }
+
+ double sum_prob = 0,zipf_value = 0;
+ for (uint32_t i = 1; i <= m_n; i++)
+ {
+ sum_prob += m_c / std::pow ((double)i,m_alpha);
+ if (sum_prob > u)
+ {
+ zipf_value = i;
+ break;
+ }
+ }
+ return zipf_value;
+}
+
+uint32_t
+ZipfRandomVariable::GetInteger (uint32_t n, uint32_t alpha)
+{
+ return static_cast<uint32_t> ( GetValue (n, alpha));
+}
+
+double
+ZipfRandomVariable::GetValue (void)
+{
+ return GetValue (m_n, m_alpha);
+}
+uint32_t
+ZipfRandomVariable::GetInteger (void)
+{
+ return (uint32_t)GetValue (m_n, m_alpha);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(ZetaRandomVariable);
+
+TypeId
+ZetaRandomVariable::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::ZetaRandomVariable")
+ .SetParent<RandomVariableStream>()
+ .AddConstructor<ZetaRandomVariable> ()
+ .AddAttribute("Alpha", "The alpha value for the zeta distribution returned by this RNG stream.",
+ DoubleValue(3.14),
+ MakeDoubleAccessor(&ZetaRandomVariable::m_alpha),
+ MakeDoubleChecker<double>())
+ ;
+ return tid;
+}
+ZetaRandomVariable::ZetaRandomVariable ()
+{
+ // m_alpha is initialized after constructor by attributes
+}
+
+double
+ZetaRandomVariable::GetAlpha (void) const
+{
+ return m_alpha;
+}
+
+double
+ZetaRandomVariable::GetValue (double alpha)
+{
+ m_b = std::pow (2.0, alpha - 1.0);
+
+ double u, v;
+ double X, T;
+ double test;
+
+ do
+ {
+ // Get a uniform random variable in [0,1].
+ u = Peek ()->RandU01 ();
+ if (IsAntithetic ())
+ {
+ u = (1 - u);
+ }
+
+ // Get a uniform random variable in [0,1].
+ v = Peek ()->RandU01 ();
+ if (IsAntithetic ())
+ {
+ v = (1 - v);
+ }
+
+ X = std::floor (std::pow (u, -1.0 / (m_alpha - 1.0)));
+ T = std::pow (1.0 + 1.0 / X, m_alpha - 1.0);
+ test = v * X * (T - 1.0) / (m_b - 1.0);
+ }
+ while ( test > (T / m_b) );
+
+ return X;
+}
+
+uint32_t
+ZetaRandomVariable::GetInteger (uint32_t alpha)
+{
+ return static_cast<uint32_t> ( GetValue (alpha));
+}
+
+double
+ZetaRandomVariable::GetValue (void)
+{
+ return GetValue (m_alpha);
+}
+uint32_t
+ZetaRandomVariable::GetInteger (void)
+{
+ return (uint32_t)GetValue (m_alpha);
+}
+
+NS_OBJECT_ENSURE_REGISTERED(DeterministicRandomVariable);
+
+TypeId
+DeterministicRandomVariable::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::DeterministicRandomVariable")
+ .SetParent<RandomVariableStream>()
+ .AddConstructor<DeterministicRandomVariable> ()
+ ;
+ return tid;
+}
+DeterministicRandomVariable::DeterministicRandomVariable ()
+ :
+ m_count (0),
+ m_next (0),
+ m_data (0)
+{
+}
+DeterministicRandomVariable::~DeterministicRandomVariable ()
+{
+ // Delete any values currently set.
+ if (m_data != 0)
+ {
+ delete[] m_data;
+ }
+}
+
+void
+DeterministicRandomVariable::SetValueArray (double* values, uint64_t length)
+{
+ // Delete any values currently set.
+ if (m_data != 0)
+ {
+ delete[] m_data;
+ }
+
+ // Make room for the values being set.
+ m_data = new double[length];
+ m_count = length;
+ m_next = length;
+
+ // Copy the values.
+ for (uint64_t i = 0; i < m_count; i++)
+ {
+ m_data[i] = values[i];
+ }
+}
+
+double
+DeterministicRandomVariable::GetValue (void)
+{
+ // Make sure the array has been set.
+ NS_ASSERT (m_count > 0);
+
+ if (m_next == m_count)
+ {
+ m_next = 0;
+ }
+ return m_data[m_next++];
+}
+
+uint32_t
+DeterministicRandomVariable::GetInteger (void)
+{
+ return (uint32_t)GetValue ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED(EmpiricalRandomVariable);
+
+// ValueCDF methods
+EmpiricalRandomVariable::ValueCDF::ValueCDF ()
+ : value (0.0),
+ cdf (0.0)
+{
+}
+EmpiricalRandomVariable::ValueCDF::ValueCDF (double v, double c)
+ : value (v),
+ cdf (c)
+{
+}
+EmpiricalRandomVariable::ValueCDF::ValueCDF (const ValueCDF& c)
+ : value (c.value),
+ cdf (c.cdf)
+{
+}
+
+TypeId
+EmpiricalRandomVariable::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::EmpiricalRandomVariable")
+ .SetParent<RandomVariableStream>()
+ .AddConstructor<EmpiricalRandomVariable> ()
+ ;
+ return tid;
+}
+EmpiricalRandomVariable::EmpiricalRandomVariable ()
+ :
+ validated (false)
+{
+}
+
+double
+EmpiricalRandomVariable::GetValue (void)
+{
+ // Return a value from the empirical distribution
+ // This code based (loosely) on code by Bruce Mah (Thanks Bruce!)
+ if (emp.size () == 0)
+ {
+ return 0.0; // HuH? No empirical data
+ }
+ if (!validated)
+ {
+ Validate (); // Insure in non-decreasing
+ }
+
+ // Get a uniform random variable in [0,1].
+ double r = Peek ()->RandU01 ();
+ if (IsAntithetic ())
+ {
+ r = (1 - r);
+ }
+
+ if (r <= emp.front ().cdf)
+ {
+ return emp.front ().value; // Less than first
+ }
+ if (r >= emp.back ().cdf)
+ {
+ return emp.back ().value; // Greater than last
+ }
+ // Binary search
+ std::vector<ValueCDF>::size_type bottom = 0;
+ std::vector<ValueCDF>::size_type top = emp.size () - 1;
+ while (1)
+ {
+ std::vector<ValueCDF>::size_type c = (top + bottom) / 2;
+ if (r >= emp[c].cdf && r < emp[c + 1].cdf)
+ { // Found it
+ return Interpolate (emp[c].cdf, emp[c + 1].cdf,
+ emp[c].value, emp[c + 1].value,
+ r);
+ }
+ // Not here, adjust bounds
+ if (r < emp[c].cdf)
+ {
+ top = c - 1;
+ }
+ else
+ {
+ bottom = c + 1;
+ }
+ }
+}
+
+uint32_t
+EmpiricalRandomVariable::GetInteger (void)
+{
+ return (uint32_t)GetValue ();
+}
+
+void EmpiricalRandomVariable::CDF (double v, double c)
+{ // Add a new empirical datapoint to the empirical cdf
+ // NOTE. These MUST be inserted in non-decreasing order
+ emp.push_back (ValueCDF (v, c));
+}
+
+void EmpiricalRandomVariable::Validate ()
+{
+ ValueCDF prior;
+ for (std::vector<ValueCDF>::size_type i = 0; i < emp.size (); ++i)
+ {
+ ValueCDF& current = emp[i];
+ if (current.value < prior.value || current.cdf < prior.cdf)
+ { // Error
+ std::cerr << "Empirical Dist error,"
+ << " current value " << current.value
+ << " prior value " << prior.value
+ << " current cdf " << current.cdf
+ << " prior cdf " << prior.cdf << std::endl;
+ NS_FATAL_ERROR ("Empirical Dist error");
+ }
+ prior = current;
+ }
+ validated = true;
+}
+
+double EmpiricalRandomVariable::Interpolate (double c1, double c2,
+ double v1, double v2, double r)
+{ // Interpolate random value in range [v1..v2) based on [c1 .. r .. c2)
+ return (v1 + ((v2 - v1) / (c2 - c1)) * (r - c1));
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/model/random-variable-stream.h Tue Jul 31 19:18:23 2012 +0200
@@ -0,0 +1,2435 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 Georgia Tech Research Corporation
+ * Copyright (c) 2011 Mathieu Lacage
+ *
+ * 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
+ *
+ * Authors: Rajib Bhattacharjea<raj.b@gatech.edu>
+ * Hadi Arbabi<marbabi@cs.odu.edu>
+ * Mathieu Lacage <mathieu.lacage@gmail.com>
+ *
+ * Modified by Mitch Watrous <watrous@u.washington.edu>
+ *
+ */
+#ifndef RANDOM_VARIABLE_STREAM_H
+#define RANDOM_VARIABLE_STREAM_H
+
+#include "type-id.h"
+#include "object.h"
+#include "attribute-helper.h"
+#include <stdint.h>
+
+namespace ns3 {
+
+class RngStream;
+
+/**
+ * \ingroup randomvariable
+ * \brief The Random Number Generator (RNG) that allows stream numbers to be set deterministically.
+ *
+ * Note: The underlying random number generation method used
+ * by NS-3 is the RngStream code by Pierre L'Ecuyer at
+ * the University of Montreal.
+ *
+ * NS-3 has a rich set of random number generators that allow stream
+ * numbers to be set deterministically if desired. Class
+ * RandomVariableStream defines the base class functionalty required
+ * for all such random number generators.
+ *
+ * By default, the underlying generator is seeded all the time with
+ * the same seed value and run number coming from the ns3::GlobalValue
+ * \ref GlobalValueRngSeed "RngSeed" and \ref GlobalValueRngRun
+ * "RngRun". Also by default, the stream number value for this RNG
+ * stream is automatically allocated.
+ */
+class RandomVariableStream : public Object
+{
+public:
+ static TypeId GetTypeId (void);
+ RandomVariableStream ();
+ virtual ~RandomVariableStream();
+
+ /**
+ * \brief Specifies the stream number for this RNG stream.
+ * \param stream The stream number for this RNG stream. -1 means "allocate a stream number automatically".
+ */
+ void SetStream (int64_t stream);
+
+ /**
+ * \brief Returns the stream number for this RNG stream.
+ * \return The stream number for this RNG stream. -1 means "allocate a stream number automatically".
+ */
+ int64_t GetStream(void) const;
+
+ /**
+ * \brief Specifies whether antithetic values should be generated.
+ * \param isAntithetic Set equal to true if antithetic values should
+ * be generated by this RNG stream.
+ */
+ void SetAntithetic(bool isAntithetic);
+
+ /**
+ * \brief Returns true if antithetic values should be generated.
+ * \return A bool value that indicates if antithetic values should
+ * be generated by this RNG stream.
+ */
+ bool IsAntithetic(void) const;
+
+ /**
+ * \brief Returns a random double from the underlying distribution
+ * \return A floating point random value.
+ */
+ virtual double GetValue (void) = 0;
+
+ /**
+ * \brief Returns a random integer integer from the underlying distribution
+ * \return Integer cast of RandomVariableStream::GetValue
+ */
+ virtual uint32_t GetInteger (void) = 0;
+
+protected:
+ /**
+ * \brief Returns a pointer to the underlying RNG stream.
+ */
+ RngStream *Peek(void) const;
+
+private:
+ // you can't copy these objects.
+ // Theoretically, it is possible to give them good copy semantics
+ // but not enough time to iron out the details.
+ RandomVariableStream (const RandomVariableStream &o);
+ RandomVariableStream &operator = (const RandomVariableStream &o);
+
+ /// Pointer to the underlying RNG stream.
+ RngStream *m_rng;
+
+ /// Indicates if antithetic values should be generated by this RNG stream.
+ bool m_isAntithetic;
+
+ /// The stream number for this RNG stream.
+ int64_t m_stream;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The uniform distribution Random Number Generator (RNG) that allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed uniform distribution. It also supports the generation of
+ * single random numbers from various uniform distributions.
+ *
+ * The low end of the range is always included and the high end
+ * of the range is always excluded.
+ *
+ * Here is an example of how to use this class:
+ * \code
+ * double min = 0.0;
+ * double max = 10.0;
+ *
+ * Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable> ();
+ * x->SetAttribute ("Min", DoubleValue (min));
+ * x->SetAttribute ("Max", DoubleValue (max));
+ *
+ * // The values returned by a uniformly distributed random
+ * // variable should always be within the range
+ * //
+ * // [min, max) .
+ * //
+ * double value = x->GetValue ();
+ * \endcode
+ */
+class UniformRandomVariable : public RandomVariableStream
+{
+public:
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Creates a uniform distribution RNG with the default range.
+ */
+ UniformRandomVariable ();
+
+ /**
+ * \brief Returns the lower bound on values that can be returned by this RNG stream.
+ * \return The lower bound on values that can be returned by this RNG stream.
+ */
+ double GetMin (void) const;
+
+ /**
+ * \brief Returns the upper bound on values that can be returned by this RNG stream.
+ * \return The upper bound on values that can be returned by this RNG stream.
+ */
+ double GetMax (void) const;
+
+ /**
+ * \brief Returns a random double from the uniform distribution with the specified range.
+ * \param min Low end of the range.
+ * \param max High end of the range.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$x\f$ is a value that
+ * would be returned normally, then \f$(max - x\f$) is the distance
+ * that \f$x\f$ would be from \f$max\f$. The value returned in the
+ * antithetic case, \f$x'\f$, is calculated as
+ *
+ * \f[
+ * x' = min + (max - x) ,
+ * \f]
+ *
+ * which is the lower bound plus the distance \f$x\f$ is from the
+ * upper bound.
+ */
+ double GetValue (double min, double max);
+
+ /**
+ * \brief Returns a random unsigned integer from a uniform distribution over the interval [min,max] including both ends.
+ * \param min Low end of the range.
+ * \param max High end of the range.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$x\f$ is a value that
+ * would be returned normally, then \f$(max - x\f$) is the distance
+ * that \f$x\f$ would be from \f$max\f$. The value returned in the
+ * antithetic case, \f$x'\f$, is calculated as
+ *
+ * \f[
+ * x' = min + (max - x) ,
+ * \f]
+ *
+ * which is the lower bound plus the distance \f$x\f$ is from the
+ * upper bound.
+ */
+ uint32_t GetInteger (uint32_t min, uint32_t max);
+
+ /**
+ * \brief Returns a random double from the uniform distribution with the range [min,max), where min and max are the current lower and upper bounds.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$x\f$ is a value that
+ * would be returned normally, then \f$(max - x\f$) is the distance
+ * that \f$x\f$ would be from \f$max\f$. The value returned in the
+ * antithetic case, \f$x'\f$, is calculated as
+ *
+ * \f[
+ * x' = min + (max - x) ,
+ * \f]
+ *
+ * which is the lower bound plus the distance \f$x\f$ is from the
+ * upper bound.
+ *
+ * Note that we have to re-implement this method here because the method is
+ * overloaded above for the two-argument variant and the c++ name resolution
+ * rules don't work well with overloads split between parent and child
+ * classes.
+ */
+ virtual double GetValue (void);
+
+ /**
+ * \brief Returns a random unsigned integer from a uniform distribution over the interval [min,max] including both ends, where min and max are the current lower and upper bounds.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$x\f$ is a value that
+ * would be returned normally, then \f$(max - x\f$) is the distance
+ * that \f$x\f$ would be from \f$max\f$. The value returned in the
+ * antithetic case, \f$x'\f$, is calculated as
+ *
+ * \f[
+ * x' = min + (max - x) ,
+ * \f]
+ *
+ * which is the lower bound plus the distance \f$x\f$ is from the
+ * upper bound.
+ */
+ virtual uint32_t GetInteger (void);
+private:
+ /// The lower bound on values that can be returned by this RNG stream.
+ double m_min;
+
+ /// The upper bound on values that can be returned by this RNG stream.
+ double m_max;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The Random Number Generator (RNG) that returns a constant.
+ *
+ * Class ConstantRandomVariable returns the same value for every sample.
+ */
+class ConstantRandomVariable : public RandomVariableStream
+{
+public:
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Creates a constant RNG with the default constant value.
+ */
+ ConstantRandomVariable ();
+
+ /**
+ * \brief Returns the constant value returned by this RNG stream.
+ * \return The constant value returned by this RNG stream.
+ */
+ double GetConstant (void) const;
+
+ /**
+ * \brief Returns the value passed in.
+ * \return The floating point value passed in.
+ */
+ double GetValue (double constant);
+ /**
+ * \brief Returns the value passed in.
+ * \return The integer value passed in.
+ */
+ uint32_t GetInteger (uint32_t constant);
+
+ /**
+ * \brief Returns the constant value returned by this RNG stream.
+ * \return The constant value returned by this RNG stream.
+ */
+ virtual double GetValue (void);
+
+ /**
+ * \brief Returns an integer cast of the constant value returned by this RNG stream.
+ * \return Integer cast of the constant value returned by this RNG stream.
+ */
+ virtual uint32_t GetInteger (void);
+
+private:
+ /// The constant value returned by this RNG stream.
+ double m_constant;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The Random Number Generator (RNG) that returns a sequential
+ * list of values
+ *
+ * Class SequentialRandomVariable defines a random number generator
+ * that returns a sequence of values. The sequence monotonically
+ * increases for a period, then wraps around to the low value and
+ * begins monotonically increasing again.
+ */
+class SequentialRandomVariable : public RandomVariableStream
+{
+public:
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Creates a sequential RNG with the default values for the sequence parameters.
+ */
+ SequentialRandomVariable ();
+
+ /**
+ * \brief Returns the first value of the sequence.
+ * \return The first value of the sequence.
+ */
+ double GetMin (void) const;
+
+ /**
+ * \brief Returns one more than the last value of the sequence.
+ * \return One more than the last value of the sequence.
+ */
+ double GetMax (void) const;
+
+ /**
+ * \brief Returns the random variable increment for the sequence.
+ * \return The random variable increment for the sequence.
+ */
+ Ptr<RandomVariableStream> GetIncrement (void) const;
+
+ /**
+ * \brief Returns the number of times each member of the sequence is repeated.
+ * \return The number of times each member of the sequence is repeated.
+ */
+ uint32_t GetConsecutive (void) const;
+
+ /**
+ * \brief Returns the next value in the sequence returned by this RNG stream.
+ * \return The next value in the sequence returned by this RNG stream.
+ *
+ * The following four parameters define the sequence. For example,
+ *
+ * - m_min = 0 (First value of the sequence)
+ * - m_max = 5 (One more than the last value of the sequence)
+ * - m_increment = 1 (Random variable increment between sequence values)
+ * - m_consecutive = 2 (Number of times each member of the sequence is repeated)
+ *
+ * creates a RNG that has the sequence 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 0, 0 ...
+ */
+ virtual double GetValue (void);
+
+ /**
+ * \brief Returns an integer cast of the next value in the sequence returned by this RNG stream.
+ * \return Integer cast of the next value in the sequence returned by this RNG stream.
+ */
+ virtual uint32_t GetInteger (void);
+
+private:
+ /// The first value of the sequence.
+ double m_min;
+
+ /// One more than the last value of the sequence.
+ double m_max;
+
+ /// The sequence random variable increment.
+ Ptr<RandomVariableStream> m_increment;
+
+ /// The number of times each member of the sequence is repeated.
+ uint32_t m_consecutive;
+
+ /// The current sequence value.
+ double m_current;
+
+ /// The number of times the sequence has been repeated.
+ uint32_t m_currentConsecutive;
+
+ /// Indicates if the current sequence value has been set.
+ bool m_isCurrentSet;
+
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The exponential distribution Random Number Generator (RNG) that allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed exponential distribution. It also supports the generation of
+ * single random numbers from various exponential distributions.
+ *
+ * The probability density function of an exponential variable
+ * is defined over the interval [0, \f$+\infty\f$) as:
+ * \f$ \alpha e^{-\alpha x} \f$
+ * where \f$ \alpha = \frac{1}{mean} \f$
+ *
+ * Since exponential distributions can theoretically return unbounded
+ * values, it is sometimes useful to specify a fixed upper limit. The
+ * bounded version is defined over the interval [0,b] as: \f$ \alpha
+ * e^{-\alpha x} \quad x \in [0,b] \f$. Note that in this case the
+ * true mean of the distribution is slightly smaller than the mean
+ * value specified: \f$ 1/\alpha - b/(e^{\alpha \, b}-1) \f$.
+ *
+ * Here is an example of how to use this class:
+ * \code
+ * double mean = 3.14;
+ * double bound = 0.0;
+ *
+ * Ptr<ExponentialRandomVariable> x = CreateObject<ExponentialRandomVariable> ();
+ * x->SetAttribute ("Mean", DoubleValue (mean));
+ * x->SetAttribute ("Bound", DoubleValue (bound));
+ *
+ * // The expected value for the mean of the values returned by an
+ * // exponentially distributed random variable is equal to mean.
+ * double value = x->GetValue ();
+ * \endcode
+ */
+class ExponentialRandomVariable : public RandomVariableStream
+{
+public:
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Creates a exponential distribution RNG with the default
+ * values for the mean and upper bound.
+ */
+ ExponentialRandomVariable ();
+
+ /**
+ * \brief Returns the mean value of the random variables returned by this RNG stream.
+ * \return The mean value of the random variables returned by this RNG stream.
+ */
+ double GetMean (void) const;
+
+ /**
+ * \brief Returns the upper bound on values that can be returned by this RNG stream.
+ * \return The upper bound on values that can be returned by this RNG stream.
+ */
+ double GetBound (void) const;
+
+ /**
+ * \brief Returns a random double from an exponential distribution with the specified mean and upper bound.
+ * \param mean Mean value of the random variables.
+ * \param bound Upper bound on values returned.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$u\f$ is a uniform variable
+ * over [0,1] and
+ *
+ * \f[
+ * x = - mean * \log(u)
+ * \f]
+ *
+ * is a value that would be returned normally, then \f$(1 - u\f$) is
+ * the distance that \f$u\f$ would be from \f$1\f$. The value
+ * returned in the antithetic case, \f$x'\f$, is calculated as
+ *
+ * \f[
+ * x' = - mean * \log(1 - u),
+ * \f]
+ *
+ * which now involves the log of the distance \f$u\f$ is from the 1.
+ */
+ double GetValue (double mean, double bound);
+
+ /**
+ * \brief Returns a random unsigned integer from an exponential distribution with the specified mean and upper bound.
+ * \param mean Mean value of the random variables.
+ * \param bound Upper bound on values returned.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$u\f$ is a uniform variable
+ * over [0,1] and
+ *
+ * \f[
+ * x = - mean * \log(u)
+ * \f]
+ *
+ * is a value that would be returned normally, then \f$(1 - u\f$) is
+ * the distance that \f$u\f$ would be from \f$1\f$. The value
+ * returned in the antithetic case, \f$x'\f$, is calculated as
+ *
+ * \f[
+ * x' = - mean * \log(1 - u),
+ * \f]
+ *
+ * which now involves the log of the distance \f$u\f$ is from the 1.
+ */
+ uint32_t GetInteger (uint32_t mean, uint32_t bound);
+
+ /**
+ * \brief Returns a random double from an exponential distribution with the current mean and upper bound.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$u\f$ is a uniform variable
+ * over [0,1] and
+ *
+ * \f[
+ * x = - mean * \log(u)
+ * \f]
+ *
+ * is a value that would be returned normally, then \f$(1 - u\f$) is
+ * the distance that \f$u\f$ would be from \f$1\f$. The value
+ * returned in the antithetic case, \f$x'\f$, is calculated as
+ *
+ * \f[
+ * x' = - mean * \log(1 - u),
+ * \f]
+ *
+ * which now involves the log of the distance \f$u\f$ is from the 1.
+ *
+ * Note that we have to re-implement this method here because the method is
+ * overloaded above for the two-argument variant and the c++ name resolution
+ * rules don't work well with overloads split between parent and child
+ * classes.
+ */
+ virtual double GetValue (void);
+
+ /**
+ * \brief Returns a random unsigned integer from an exponential distribution with the current mean and upper bound.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$u\f$ is a uniform variable
+ * over [0,1] and
+ *
+ * \f[
+ * x = - mean * \log(u)
+ * \f]
+ *
+ * is a value that would be returned normally, then \f$(1 - u\f$) is
+ * the distance that \f$u\f$ would be from \f$1\f$. The value
+ * returned in the antithetic case, \f$x'\f$, is calculated as
+ *
+ * \f[
+ * x' = - mean * \log(1 - u),
+ * \f]
+ *
+ * which now involves the log of the distance \f$u\f$ is from the 1.
+ */
+ virtual uint32_t GetInteger (void);
+
+private:
+ /// The mean value of the random variables returned by this RNG stream.
+ double m_mean;
+
+ /// The upper bound on values that can be returned by this RNG stream.
+ double m_bound;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The Pareto distribution Random Number Generator (RNG) that allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed Pareto distribution. It also supports the generation of
+ * single random numbers from various Pareto distributions.
+ *
+ * The probability density function of a Pareto variable is defined
+ * over the range [\f$x_m\f$,\f$+\infty\f$) as: \f$ k \frac{x_m^k}{x^{k+1}}\f$
+ * where \f$x_m > 0\f$ is called the scale parameter and \f$ k > 0\f$
+ * is called the pareto index or shape.
+ *
+ * The parameter \f$ x_m \f$ can be infered from the mean and the parameter \f$ k \f$
+ * with the equation \f$ x_m = mean \frac{k-1}{k}, k > 1\f$.
+ *
+ * Since Pareto distributions can theoretically return unbounded values,
+ * it is sometimes useful to specify a fixed upper limit. Note however
+ * when the upper limit is specified, the true mean of the distribution
+ * is slightly smaller than the mean value specified.
+ *
+ * Here is an example of how to use this class:
+ * \code
+ * double mean = 5.0;
+ * double shape = 2.0;
+ *
+ * Ptr<ParetoRandomVariable> x = CreateObject<ParetoRandomVariable> ();
+ * x->SetAttribute ("Mean", DoubleValue (mean));
+ * x->SetAttribute ("Shape", DoubleValue (shape));
+ *
+ * // The expected value for the mean of the values returned by a
+ * // Pareto distributed random variable is
+ * //
+ * // shape * scale
+ * // E[value] = --------------- ,
+ * // shape - 1
+ * //
+ * // where
+ * //
+ * // scale = mean * (shape - 1.0) / shape .
+ * //
+ * double value = x->GetValue ();
+ * \endcode
+ */
+class ParetoRandomVariable : public RandomVariableStream
+{
+public:
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Creates a Pareto distribution RNG with the default
+ * values for the mean, the shape, and upper bound.
+ */
+ ParetoRandomVariable ();
+
+ /**
+ * \brief Returns the mean parameter for the Pareto distribution returned by this RNG stream.
+ * \return The mean parameter for the Pareto distribution returned by this RNG stream.
+ */
+ double GetMean (void) const;
+
+ /**
+ * \brief Returns the shape parameter for the Pareto distribution returned by this RNG stream.
+ * \return The shape parameter for the Pareto distribution returned by this RNG stream.
+ */
+ double GetShape (void) const;
+
+ /**
+ * \brief Returns the upper bound on values that can be returned by this RNG stream.
+ * \return The upper bound on values that can be returned by this RNG stream.
+ */
+ double GetBound (void) const;
+
+ /**
+ * \brief Returns a random double from a Pareto distribution with the specified mean, shape, and upper bound.
+ * \param mean Mean parameter for the Pareto distribution.
+ * \param shape Shape parameter for the Pareto distribution.
+ * \param bound Upper bound on values returned.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$u\f$ is a uniform variable
+ * over [0,1] and
+ *
+ * \f[
+ * x = \frac{scale}{u^{\frac{1}{shape}}}
+ * \f]
+ *
+ * is a value that would be returned normally, where
+ *
+ * \f[
+ * scale = mean * (shape - 1.0) / shape .
+ * \f]
+ *
+ * Then \f$(1 - u\f$) is the distance that \f$u\f$ would be from
+ * \f$1\f$. The value returned in the antithetic case, \f$x'\f$, is
+ * calculated as
+ *
+ * \f[
+ * x' = \frac{scale}{{(1 - u)}^{\frac{1}{shape}}} ,
+ * \f]
+ *
+ * which now involves the distance \f$u\f$ is from 1 in the denonator.
+ */
+ double GetValue (double mean, double shape, double bound);
+
+ /**
+ * \brief Returns a random unsigned integer from a Pareto distribution with the specified mean, shape, and upper bound.
+ * \param mean Mean parameter for the Pareto distribution.
+ * \param shape Shape parameter for the Pareto distribution.
+ * \param bound Upper bound on values returned.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$u\f$ is a uniform variable
+ * over [0,1] and
+ *
+ * \f[
+ * x = \frac{scale}{u^{\frac{1}{shape}}}
+ * \f]
+ *
+ * is a value that would be returned normally, where
+ *
+ * \f[
+ * scale = mean * (shape - 1.0) / shape .
+ * \f]
+ *
+ * Then \f$(1 - u\f$) is the distance that \f$u\f$ would be from
+ * \f$1\f$. The value returned in the antithetic case, \f$x'\f$, is
+ * calculated as
+ *
+ * \f[
+ * x' = \frac{scale}{{(1 - u)}^{\frac{1}{shape}}} ,
+ * \f]
+ *
+ * which now involves the distance \f$u\f$ is from 1 in the denonator.
+ */
+ uint32_t GetInteger (uint32_t mean, uint32_t shape, uint32_t bound);
+
+ /**
+ * \brief Returns a random double from a Pareto distribution with the current mean, shape, and upper bound.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$u\f$ is a uniform variable
+ * over [0,1] and
+ *
+ * \f[
+ * x = \frac{scale}{u^{\frac{1}{shape}}}
+ * \f]
+ *
+ * is a value that would be returned normally, where
+ *
+ * \f[
+ * scale = mean * (shape - 1.0) / shape .
+ * \f]
+ *
+ * Then \f$(1 - u\f$) is the distance that \f$u\f$ would be from
+ * \f$1\f$. The value returned in the antithetic case, \f$x'\f$, is
+ * calculated as
+ *
+ * \f[
+ * x' = \frac{scale}{{(1 - u)}^{\frac{1}{shape}}} ,
+ * \f]
+ *
+ * which now involves the distance \f$u\f$ is from 1 in the denonator.
+ *
+ * Note that we have to re-implement this method here because the method is
+ * overloaded above for the three-argument variant and the c++ name resolution
+ * rules don't work well with overloads split between parent and child
+ * classes.
+ */
+ virtual double GetValue (void);
+
+ /**
+ * \brief Returns a random unsigned integer from a Pareto distribution with the current mean, shape, and upper bound.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$u\f$ is a uniform variable
+ * over [0,1] and
+ *
+ * \f[
+ * x = \frac{scale}{u^{\frac{1}{shape}}}
+ * \f]
+ *
+ * is a value that would be returned normally, where
+ *
+ * \f[
+ * scale = mean * (shape - 1.0) / shape .
+ * \f]
+ *
+ * Then \f$(1 - u\f$) is the distance that \f$u\f$ would be from
+ * \f$1\f$. The value returned in the antithetic case, \f$x'\f$, is
+ * calculated as
+ *
+ * \f[
+ * x' = \frac{scale}{{(1 - u)}^{\frac{1}{shape}}} ,
+ * \f]
+ *
+ * which now involves the distance \f$u\f$ is from 1 in the denonator.
+ */
+ virtual uint32_t GetInteger (void);
+
+private:
+ /// The mean parameter for the Pareto distribution returned by this RNG stream.
+ double m_mean;
+
+ /// The shape parameter for the Pareto distribution returned by this RNG stream.
+ double m_shape;
+
+ /// The upper bound on values that can be returned by this RNG stream.
+ double m_bound;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The Weibull distribution Random Number Generator (RNG) that allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed Weibull distribution. It also supports the generation of
+ * single random numbers from various Weibull distributions.
+ *
+ * The probability density function is defined over the interval [0, \f$+\infty\f$]
+ * as: \f$ \frac{k}{\lambda}\left(\frac{x}{\lambda}\right)^{k-1}e^{-\left(\frac{x}{\lambda}\right)^k} \f$
+ * where \f$ k > 0\f$ is the shape parameter and \f$ \lambda > 0\f$ is the scale parameter. The
+ * specified mean is related to the scale and shape parameters by the following relation:
+ * \f$ mean = \lambda\Gamma\left(1+\frac{1}{k}\right) \f$ where \f$ \Gamma \f$ is the Gamma function.
+ *
+ * Since Weibull distributions can theoretically return unbounded values,
+ * it is sometimes useful to specify a fixed upper limit. Note however
+ * when the upper limit is specified, the true mean of the distribution
+ * is slightly smaller than the mean value specified.
+ *
+ * Here is an example of how to use this class:
+ * \code
+ * double scale = 5.0;
+ * double shape = 1.0;
+ *
+ * Ptr<WeibullRandomVariable> x = CreateObject<WeibullRandomVariable> ();
+ * x->SetAttribute ("Scale", DoubleValue (scale));
+ * x->SetAttribute ("Shape", DoubleValue (shape));
+ *
+ * // The expected value for the mean of the values returned by a
+ * // Weibull distributed random variable is
+ * //
+ * // E[value] = scale * Gamma(1 + 1 / shape) ,
+ * //
+ * // where Gamma() is the Gamma function. Note that
+ * //
+ * // Gamma(n) = (n - 1)!
+ * //
+ * // if n is a positive integer.
+ * //
+ * // For this example,
+ * //
+ * // Gamma(1 + 1 / shape) = Gamma(1 + 1 / 1)
+ * // = Gamma(2)
+ * // = (2 - 1)!
+ * // = 1
+ * //
+ * // which means
+ * //
+ * // E[value] = scale .
+ * //
+ * double value = x->GetValue ();
+ * \endcode
+ */
+class WeibullRandomVariable : public RandomVariableStream
+{
+public:
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Creates a Weibull distribution RNG with the default
+ * values for the scale, shape, and upper bound.
+ */
+ WeibullRandomVariable ();
+
+ /**
+ * \brief Returns the scale parameter for the Weibull distribution returned by this RNG stream.
+ * \return The scale parameter for the Weibull distribution returned by this RNG stream.
+ */
+ double GetScale (void) const;
+
+ /**
+ * \brief Returns the shape parameter for the Weibull distribution returned by this RNG stream.
+ * \return The shape parameter for the Weibull distribution returned by this RNG stream.
+ */
+ double GetShape (void) const;
+
+ /**
+ * \brief Returns the upper bound on values that can be returned by this RNG stream.
+ * \return The upper bound on values that can be returned by this RNG stream.
+ */
+ double GetBound (void) const;
+
+ /**
+ * \brief Returns a random double from a Weibull distribution with the specified scale, shape, and upper bound.
+ * \param scale Scale parameter for the Weibull distribution.
+ * \param shape Shape parameter for the Weibull distribution.
+ * \param bound Upper bound on values returned.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$u\f$ is a uniform variable
+ * over [0,1] and
+ *
+ * \f[
+ * x = scale * {(-\log(u))}^{\frac{1}{shape}}
+ * \f]
+ *
+ * is a value that would be returned normally, then \f$(1 - u\f$) is
+ * the distance that \f$u\f$ would be from \f$1\f$. The value
+ * returned in the antithetic case, \f$x'\f$, is calculated as
+ *
+ * \f[
+ * x' = scale * {(-\log(1 - u))}^{\frac{1}{shape}} ,
+ * \f]
+ *
+ * which now involves the log of the distance \f$u\f$ is from 1.
+ */
+ double GetValue (double scale, double shape, double bound);
+
+ /**
+ * \brief Returns a random unsigned integer from a Weibull distribution with the specified scale, shape, and upper bound.
+ * \param scale Scale parameter for the Weibull distribution.
+ * \param shape Shape parameter for the Weibull distribution.
+ * \param bound Upper bound on values returned.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$u\f$ is a uniform variable
+ * over [0,1] and
+ *
+ * \f[
+ * x = scale * {(-\log(u))}^{\frac{1}{shape}}
+ * \f]
+ *
+ * is a value that would be returned normally, then \f$(1 - u\f$) is
+ * the distance that \f$u\f$ would be from \f$1\f$. The value
+ * returned in the antithetic case, \f$x'\f$, is calculated as
+ *
+ * \f[
+ * x' = scale * {(-\log(1 - u))}^{\frac{1}{shape}} ,
+ * \f]
+ *
+ * which now involves the log of the distance \f$u\f$ is from 1.
+ */
+ uint32_t GetInteger (uint32_t scale, uint32_t shape, uint32_t bound);
+
+ /**
+ * \brief Returns a random double from a Weibull distribution with the current scale, shape, and upper bound.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$u\f$ is a uniform variable
+ * over [0,1] and
+ *
+ * \f[
+ * x = scale * {(-\log(u))}^{\frac{1}{shape}}
+ * \f]
+ *
+ * is a value that would be returned normally, then \f$(1 - u\f$) is
+ * the distance that \f$u\f$ would be from \f$1\f$. The value
+ * returned in the antithetic case, \f$x'\f$, is calculated as
+ *
+ * \f[
+ * x' = scale * {(-\log(1 - u))}^{\frac{1}{shape}} ,
+ * \f]
+ *
+ * which now involves the log of the distance \f$u\f$ is from 1.
+ *
+ * Note that we have to re-implement this method here because the method is
+ * overloaded above for the three-argument variant and the c++ name resolution
+ * rules don't work well with overloads split between parent and child
+ * classes.
+ */
+ virtual double GetValue (void);
+
+ /**
+ * \brief Returns a random unsigned integer from a Weibull distribution with the current scale, shape, and upper bound.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$u\f$ is a uniform variable
+ * over [0,1] and
+ *
+ * \f[
+ * x = scale * {(-\log(u))}^{\frac{1}{shape}}
+ * \f]
+ *
+ * is a value that would be returned normally, then \f$(1 - u\f$) is
+ * the distance that \f$u\f$ would be from \f$1\f$. The value
+ * returned in the antithetic case, \f$x'\f$, is calculated as
+ *
+ * \f[
+ * x' = scale * {(-\log(1 - u))}^{\frac{1}{shape}} ,
+ * \f]
+ *
+ * which now involves the log of the distance \f$u\f$ is from 1.
+ */
+ virtual uint32_t GetInteger (void);
+
+private:
+ /// The scale parameter for the Weibull distribution returned by this RNG stream.
+ double m_scale;
+
+ /// The shape parameter for the Weibull distribution returned by this RNG stream.
+ double m_shape;
+
+ /// The upper bound on values that can be returned by this RNG stream.
+ double m_bound;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The normal (Gaussian) distribution Random Number Generator
+ * (RNG) that allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed normal distribution. It also supports the generation of
+ * single random numbers from various normal distributions.
+ *
+ * The density probability function is defined over the interval (\f$-\infty\f$,\f$+\infty\f$)
+ * as: \f$ \frac{1}{\sigma\sqrt{2\pi}} e^{-\frac{(x-\mu)^2}{s\sigma^2}}\f$
+ * where \f$ mean = \mu \f$ and \f$ variance = \sigma^2 \f$
+ *
+ * Since normal distributions can theoretically return unbounded
+ * values, it is sometimes useful to specify a fixed bound. The
+ * NormalRandomVariable is bounded symmetrically about the mean by
+ * this bound, i.e. its values are confined to the interval
+ * [\f$mean-bound\f$,\f$mean+bound\f$].
+ *
+ * Here is an example of how to use this class:
+ * \code
+ * double mean = 5.0;
+ * double variance = 2.0;
+ *
+ * Ptr<NormalRandomVariable> x = CreateObject<NormalRandomVariable> ();
+ * x->SetAttribute ("Mean", DoubleValue (mean));
+ * x->SetAttribute ("Variance", DoubleValue (variance));
+ *
+ * // The expected value for the mean of the values returned by a
+ * // normally distributed random variable is equal to mean.
+ * double value = x->GetValue ();
+ * \endcode
+ */
+class NormalRandomVariable : public RandomVariableStream
+{
+public:
+ static const double INFINITE_VALUE;
+
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Creates a normal distribution RNG with the default
+ * values for the mean, variance, and bound.
+ */
+ NormalRandomVariable ();
+
+ /**
+ * \brief Returns the mean value for the normal distribution returned by this RNG stream.
+ * \return The mean value for the normal distribution returned by this RNG stream.
+ */
+ double GetMean (void) const;
+
+ /**
+ * \brief Returns the variance value for the normal distribution returned by this RNG stream.
+ * \return The variance value for the normal distribution returned by this RNG stream.
+ */
+ double GetVariance (void) const;
+
+ /**
+ * \brief Returns the bound on values that can be returned by this RNG stream.
+ * \return The bound on values that can be returned by this RNG stream.
+ */
+ double GetBound (void) const;
+
+ /**
+ * \brief Returns a random double from a normal distribution with the specified mean, variance, and bound.
+ * \param mean Mean value for the normal distribution.
+ * \param variance Variance value for the normal distribution.
+ * \param bound Bound on values returned.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u1\f$ and \f$u2\f$ are uniform variables
+ * over [0,1], then the values that would be returned normally, \f$x1\f$ and \f$x2\f$, are calculated as follows:
+ *
+ * \f{eqnarray*}{
+ * v1 & = & 2 * u1 - 1 \\
+ * v2 & = & 2 * u2 - 1 \\
+ * w & = & v1 * v1 + v2 * v2 \\
+ * y & = & \sqrt{\frac{-2 * \log(w)}{w}} \\
+ * x1 & = & mean + v1 * y * \sqrt{variance} \\
+ * x2 & = & mean + v2 * y * \sqrt{variance} .
+ * \f}
+ *
+ * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+ * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+ * The antithetic values returned, \f$x1'\f$ and \f$x2'\f$, are
+ * calculated as follows:
+ *
+ * \f{eqnarray*}{
+ * v1' & = & 2 * (1 - u1) - 1 \\
+ * v2' & = & 2 * (1 - u2) - 1 \\
+ * w' & = & v1' * v1' + v2' * v2' \\
+ * y' & = & \sqrt{\frac{-2 * \log(w')}{w'}} \\
+ * x1' & = & mean + v1' * y' * \sqrt{variance} \\
+ * x2' & = & mean + v2' * y' * \sqrt{variance} ,
+ * \f}
+ *
+ * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+ */
+ double GetValue (double mean, double variance, double bound);
+
+ /**
+ * \brief Returns a random unsigned integer from a normal distribution with the specified mean, variance, and bound.
+ * \param mean Mean value for the normal distribution.
+ * \param variance Variance value for the normal distribution.
+ * \param bound Bound on values returned.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u1\f$ and \f$u2\f$ are uniform variables
+ * over [0,1], then the values that would be returned normally, \f$x1\f$ and \f$x2\f$, are calculated as follows:
+ *
+ * \f{eqnarray*}{
+ * v1 & = & 2 * u1 - 1 \\
+ * v2 & = & 2 * u2 - 1 \\
+ * w & = & v1 * v1 + v2 * v2 \\
+ * y & = & \sqrt{\frac{-2 * \log(w)}{w}} \\
+ * x1 & = & mean + v1 * y * \sqrt{variance} \\
+ * x2 & = & mean + v2 * y * \sqrt{variance} .
+ * \f}
+ *
+ * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+ * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+ * The antithetic values returned, \f$x1'\f$ and \f$x2'\f$, are
+ * calculated as follows:
+ *
+ * \f{eqnarray*}{
+ * v1' & = & 2 * (1 - u1) - 1 \\
+ * v2' & = & 2 * (1 - u2) - 1 \\
+ * w' & = & v1' * v1' + v2' * v2' \\
+ * y' & = & \sqrt{\frac{-2 * \log(w')}{w'}} \\
+ * x1' & = & mean + v1' * y' * \sqrt{variance} \\
+ * x2' & = & mean + v2' * y' * \sqrt{variance} ,
+ * \f}
+ *
+ * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+ */
+ uint32_t GetInteger (uint32_t mean, uint32_t variance, uint32_t bound);
+
+ /**
+ * \brief Returns a random double from a normal distribution with the current mean, variance, and bound.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u1\f$ and \f$u2\f$ are uniform variables
+ * over [0,1], then the values that would be returned normally, \f$x1\f$ and \f$x2\f$, are calculated as follows:
+ *
+ * \f{eqnarray*}{
+ * v1 & = & 2 * u1 - 1 \\
+ * v2 & = & 2 * u2 - 1 \\
+ * w & = & v1 * v1 + v2 * v2 \\
+ * y & = & \sqrt{\frac{-2 * \log(w)}{w}} \\
+ * x1 & = & mean + v1 * y * \sqrt{variance} \\
+ * x2 & = & mean + v2 * y * \sqrt{variance} .
+ * \f}
+ *
+ * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+ * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+ * The antithetic values returned, \f$x1'\f$ and \f$x2'\f$, are
+ * calculated as follows:
+ *
+ * \f{eqnarray*}{
+ * v1' & = & 2 * (1 - u1) - 1 \\
+ * v2' & = & 2 * (1 - u2) - 1 \\
+ * w' & = & v1' * v1' + v2' * v2' \\
+ * y' & = & \sqrt{\frac{-2 * \log(w')}{w'}} \\
+ * x1' & = & mean + v1' * y' * \sqrt{variance} \\
+ * x2' & = & mean + v2' * y' * \sqrt{variance} ,
+ * \f}
+ *
+ * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+ *
+ * Note that we have to re-implement this method here because the method is
+ * overloaded above for the three-argument variant and the c++ name resolution
+ * rules don't work well with overloads split between parent and child
+ * classes.
+ */
+ virtual double GetValue (void);
+
+ /**
+ * \brief Returns a random unsigned integer from a normal distribution with the current mean, variance, and bound.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u1\f$ and \f$u2\f$ are uniform variables
+ * over [0,1], then the values that would be returned normally, \f$x1\f$ and \f$x2\f$, are calculated as follows:
+ *
+ * \f{eqnarray*}{
+ * v1 & = & 2 * u1 - 1 \\
+ * v2 & = & 2 * u2 - 1 \\
+ * w & = & v1 * v1 + v2 * v2 \\
+ * y & = & \sqrt{\frac{-2 * \log(w)}{w}} \\
+ * x1 & = & mean + v1 * y * \sqrt{variance} \\
+ * x2 & = & mean + v2 * y * \sqrt{variance} .
+ * \f}
+ *
+ * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+ * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+ * The antithetic values returned, \f$x1'\f$ and \f$x2'\f$, are
+ * calculated as follows:
+ *
+ * \f{eqnarray*}{
+ * v1' & = & 2 * (1 - u1) - 1 \\
+ * v2' & = & 2 * (1 - u2) - 1 \\
+ * w' & = & v1' * v1' + v2' * v2' \\
+ * y' & = & \sqrt{\frac{-2 * \log(w')}{w'}} \\
+ * x1' & = & mean + v1' * y' * \sqrt{variance} \\
+ * x2' & = & mean + v2' * y' * \sqrt{variance} ,
+ * \f}
+ *
+ * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+ */
+ virtual uint32_t GetInteger (void);
+
+private:
+ /// The mean value for the normal distribution returned by this RNG stream.
+ double m_mean;
+
+ /// The variance value for the normal distribution returned by this RNG stream.
+ double m_variance;
+
+ /// The bound on values that can be returned by this RNG stream.
+ double m_bound;
+
+ /// True if the next value is valid.
+ bool m_nextValid;
+
+ /// The algorithm produces two values at a time.
+ double m_next;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The log-normal distribution Random Number Generator
+ * (RNG) that allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed log-normal distribution. It also supports the generation of
+ * single random numbers from various log-normal distributions.
+ *
+ * LogNormalRandomVariable defines a random variable with a log-normal
+ * distribution. If one takes the natural logarithm of random
+ * variable following the log-normal distribution, the obtained values
+ * follow a normal distribution.
+ *
+ * The probability density function is defined over the interval [0,\f$+\infty\f$) as:
+ * \f$ \frac{1}{x\sigma\sqrt{2\pi}} e^{-\frac{(ln(x) - \mu)^2}{2\sigma^2}}\f$
+ * where \f$ mean = e^{\mu+\frac{\sigma^2}{2}} \f$ and
+ * \f$ variance = (e^{\sigma^2}-1)e^{2\mu+\sigma^2}\f$
+ *
+ * The \f$ \mu \f$ and \f$ \sigma \f$ parameters can be calculated instead if
+ * the mean and variance are known with the following equations:
+ * \f$ \mu = ln(mean) - \frac{1}{2}ln\left(1+\frac{variance}{mean^2}\right)\f$, and,
+ * \f$ \sigma = \sqrt{ln\left(1+\frac{variance}{mean^2}\right)}\f$
+ *
+ * Here is an example of how to use this class:
+ * \code
+ * double mu = 5.0;
+ * double sigma = 2.0;
+ *
+ * Ptr<LogNormalRandomVariable> x = CreateObject<LogNormalRandomVariable> ();
+ * x->SetAttribute ("Mu", DoubleValue (mu));
+ * x->SetAttribute ("Sigma", DoubleValue (sigma));
+ *
+ * // The expected value for the mean of the values returned by a
+ * // log-normally distributed random variable is equal to
+ * //
+ * // 2
+ * // mu + sigma / 2
+ * // E[value] = e .
+ * //
+ * double value = x->GetValue ();
+ * \endcode
+ */
+class LogNormalRandomVariable : public RandomVariableStream
+{
+public:
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Creates a log-normal distribution RNG with the default
+ * values for mu and sigma.
+ */
+ LogNormalRandomVariable ();
+
+ /**
+ * \brief Returns the mu value for the log-normal distribution returned by this RNG stream.
+ * \return The mu value for the log-normal distribution returned by this RNG stream.
+ */
+ double GetMu (void) const;
+
+ /**
+ * \brief Returns the sigma value for the log-normal distribution returned by this RNG stream.
+ * \return The sigma value for the log-normal distribution returned by this RNG stream.
+ */
+ double GetSigma (void) const;
+
+ /**
+ * \brief Returns a random double from a log-normal distribution with the specified mu and sigma.
+ * \param mu Mu value for the log-normal distribution.
+ * \param sigma Sigma value for the log-normal distribution.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u1\f$ and \f$u2\f$ are uniform variables
+ * over [0,1], then the value that would be returned normally, \f$x\f$, is calculated as follows:
+ *
+ * \f{eqnarray*}{
+ * v1 & = & -1 + 2 * u1 \\
+ * v2 & = & -1 + 2 * u2 \\
+ * r2 & = & v1 * v1 + v2 * v2 \\
+ * normal & = & v1 * \sqrt{\frac{-2.0 * \log{r2}}{r2}} \\
+ * x & = & \exp{sigma * normal + mu} .
+ * \f}
+ *
+ * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+ * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+ * The antithetic value returned, \f$x'\f$, is calculated as
+ * follows:
+ *
+ * \f{eqnarray*}{
+ * v1' & = & -1 + 2 * (1 - u1) \\
+ * v2' & = & -1 + 2 * (1 - u2) \\
+ * r2' & = & v1' * v1' + v2' * v2' \\
+ * normal' & = & v1' * \sqrt{\frac{-2.0 * \log{r2'}}{r2'}} \\
+ * x' & = & \exp{sigma * normal' + mu} .
+ * \f}
+ *
+ * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+ */
+ double GetValue (double mu, double sigma);
+
+ /**
+ * \brief Returns a random unsigned integer from a log-normal distribution with the specified mu and sigma.
+ * \param mu Mu value for the log-normal distribution.
+ * \param sigma Sigma value for the log-normal distribution.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u1\f$ and \f$u2\f$ are uniform variables
+ * over [0,1], then the value that would be returned normally, \f$x\f$, is calculated as follows:
+ *
+ * \f{eqnarray*}{
+ * v1 & = & -1 + 2 * u1 \\
+ * v2 & = & -1 + 2 * u2 \\
+ * r2 & = & v1 * v1 + v2 * v2 \\
+ * normal & = & v1 * \sqrt{\frac{-2.0 * \log{r2}}{r2}} \\
+ * x & = & \exp{sigma * normal + mu} .
+ * \f}
+ *
+ * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+ * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+ * The antithetic value returned, \f$x'\f$, is calculated as
+ * follows:
+ *
+ * \f{eqnarray*}{
+ * v1' & = & -1 + 2 * (1 - u1) \\
+ * v2' & = & -1 + 2 * (1 - u2) \\
+ * r2' & = & v1' * v1' + v2' * v2' \\
+ * normal' & = & v1' * \sqrt{\frac{-2.0 * \log{r2'}}{r2'}} \\
+ * x' & = & \exp{sigma * normal' + mu} .
+ * \f}
+ *
+ * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+ */
+ uint32_t GetInteger (uint32_t mu, uint32_t sigma);
+
+ /**
+ * \brief Returns a random double from a log-normal distribution with the current mu and sigma.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u1\f$ and \f$u2\f$ are uniform variables
+ * over [0,1], then the value that would be returned normally, \f$x\f$, is calculated as follows:
+ *
+ * \f{eqnarray*}{
+ * v1 & = & -1 + 2 * u1 \\
+ * v2 & = & -1 + 2 * u2 \\
+ * r2 & = & v1 * v1 + v2 * v2 \\
+ * normal & = & v1 * \sqrt{\frac{-2.0 * \log{r2}}{r2}} \\
+ * x & = & \exp{sigma * normal + mu} .
+ * \f}
+ *
+ * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+ * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+ * The antithetic value returned, \f$x'\f$, is calculated as
+ * follows:
+ *
+ * \f{eqnarray*}{
+ * v1' & = & -1 + 2 * (1 - u1) \\
+ * v2' & = & -1 + 2 * (1 - u2) \\
+ * r2' & = & v1' * v1' + v2' * v2' \\
+ * normal' & = & v1' * \sqrt{\frac{-2.0 * \log{r2'}}{r2'}} \\
+ * x' & = & \exp{sigma * normal' + mu} .
+ * \f}
+ *
+ * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+ *
+ * Note that we have to re-implement this method here because the method is
+ * overloaded above for the two-argument variant and the c++ name resolution
+ * rules don't work well with overloads split between parent and child
+ * classes.
+ */
+ virtual double GetValue (void);
+
+ /**
+ * \brief Returns a random unsigned integer from a log-normal distribution with the current mu and sigma.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u1\f$ and \f$u2\f$ are uniform variables
+ * over [0,1], then the value that would be returned normally, \f$x\f$, is calculated as follows:
+ *
+ * \f{eqnarray*}{
+ * v1 & = & -1 + 2 * u1 \\
+ * v2 & = & -1 + 2 * u2 \\
+ * r2 & = & v1 * v1 + v2 * v2 \\
+ * normal & = & v1 * \sqrt{\frac{-2.0 * \log{r2}}{r2}} \\
+ * x & = & \exp{sigma * normal + mu} .
+ * \f}
+ *
+ * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+ * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+ * The antithetic value returned, \f$x'\f$, is calculated as
+ * follows:
+ *
+ * \f{eqnarray*}{
+ * v1' & = & -1 + 2 * (1 - u1) \\
+ * v2' & = & -1 + 2 * (1 - u2) \\
+ * r2' & = & v1' * v1' + v2' * v2' \\
+ * normal' & = & v1' * \sqrt{\frac{-2.0 * \log{r2'}}{r2'}} \\
+ * x' & = & \exp{sigma * normal' + mu} .
+ * \f}
+ *
+ * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+ */
+ virtual uint32_t GetInteger (void);
+
+private:
+ /// The mu value for the log-normal distribution returned by this RNG stream.
+ double m_mu;
+
+ /// The sigma value for the log-normal distribution returned by this RNG stream.
+ double m_sigma;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The gamma distribution Random Number Generator (RNG) that
+ * allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed gamma distribution. It also supports the generation of
+ * single random numbers from various gamma distributions.
+ *
+ * The probability density function is defined over the interval [0,\f$+\infty\f$) as:
+ * \f$ x^{\alpha-1} \frac{e^{-\frac{x}{\beta}}}{\beta^\alpha \Gamma(\alpha)}\f$
+ * where \f$ mean = \alpha\beta \f$ and
+ * \f$ variance = \alpha \beta^2\f$
+ *
+ * Here is an example of how to use this class:
+ * \code
+ * double alpha = 5.0;
+ * double beta = 2.0;
+ *
+ * Ptr<GammaRandomVariable> x = CreateObject<GammaRandomVariable> ();
+ * x->SetAttribute ("Alpha", DoubleValue (alpha));
+ * x->SetAttribute ("Beta", DoubleValue (beta));
+ *
+ * // The expected value for the mean of the values returned by a
+ * // gammaly distributed random variable is equal to
+ * //
+ * // E[value] = alpha * beta .
+ * //
+ * double value = x->GetValue ();
+ * \endcode
+ */
+class GammaRandomVariable : public RandomVariableStream
+{
+public:
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Creates a gamma distribution RNG with the default values
+ * for alpha and beta.
+ */
+ GammaRandomVariable ();
+
+ /**
+ * \brief Returns the alpha value for the gamma distribution returned by this RNG stream.
+ * \return The alpha value for the gamma distribution returned by this RNG stream.
+ */
+ double GetAlpha (void) const;
+
+ /**
+ * \brief Returns the beta value for the gamma distribution returned by this RNG stream.
+ * \return The beta value for the gamma distribution returned by this RNG stream.
+ */
+ double GetBeta (void) const;
+
+ /**
+ * \brief Returns a random double from a gamma distribution with the specified alpha and beta.
+ * \param alpha Alpha value for the gamma distribution.
+ * \param beta Beta value for the gamma distribution.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ */
+ double GetValue (double alpha, double beta);
+
+ /**
+ * \brief Returns a random unsigned integer from a gamma distribution with the specified alpha and beta.
+ * \param alpha Alpha value for the gamma distribution.
+ * \param beta Beta value for the gamma distribution.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ */
+ uint32_t GetInteger (uint32_t alpha, uint32_t beta);
+
+ /**
+ * \brief Returns a random double from a gamma distribution with the current alpha and beta.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ *
+ * Note that we have to re-implement this method here because the method is
+ * overloaded above for the two-argument variant and the c++ name resolution
+ * rules don't work well with overloads split between parent and child
+ * classes.
+ */
+ virtual double GetValue (void);
+
+ /**
+ * \brief Returns a random unsigned integer from a gamma distribution with the current alpha and beta.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ */
+ virtual uint32_t GetInteger (void);
+
+private:
+ /**
+ * \brief Returns a random double from a normal distribution with the specified mean, variance, and bound.
+ * \param mean Mean value for the normal distribution.
+ * \param variance Variance value for the normal distribution.
+ * \param bound Bound on values returned.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u1\f$ and \f$u2\f$ are uniform variables
+ * over [0,1], then the values that would be returned normally, \f$x1\f$ and \f$x2\f$, are calculated as follows:
+ *
+ * \f{eqnarray*}{
+ * v1 & = & 2 * u1 - 1 \\
+ * v2 & = & 2 * u2 - 1 \\
+ * w & = & v1 * v1 + v2 * v2 \\
+ * y & = & \sqrt{\frac{-2 * \log(w)}{w}} \\
+ * x1 & = & mean + v1 * y * \sqrt{variance} \\
+ * x2 & = & mean + v2 * y * \sqrt{variance} .
+ * \f}
+ *
+ * For the antithetic case, \f$(1 - u1\f$) and \f$(1 - u2\f$) are
+ * the distances that \f$u1\f$ and \f$u2\f$ would be from \f$1\f$.
+ * The antithetic values returned, \f$x1'\f$ and \f$x2'\f$, are
+ * calculated as follows:
+ *
+ * \f{eqnarray*}{
+ * v1' & = & 2 * (1 - u1) - 1 \\
+ * v2' & = & 2 * (1 - u2) - 1 \\
+ * w' & = & v1' * v1' + v2' * v2' \\
+ * y' & = & \sqrt{\frac{-2 * \log(w')}{w'}} \\
+ * x1' & = & mean + v1' * y' * \sqrt{variance} \\
+ * x2' & = & mean + v2' * y' * \sqrt{variance} ,
+ * \f}
+ *
+ * which now involves the distances \f$u1\f$ and \f$u2\f$ are from 1.
+ */
+ double GetNormalValue (double mean, double variance, double bound);
+
+ /// The alpha value for the gamma distribution returned by this RNG stream.
+ double m_alpha;
+
+ /// The beta value for the gamma distribution returned by this RNG stream.
+ double m_beta;
+
+ /// True if the next normal value is valid.
+ bool m_nextValid;
+
+ /// The algorithm produces two normal values at a time.
+ double m_next;
+
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The Erlang distribution Random Number Generator (RNG) that
+ * allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed Erlang distribution. It also supports the generation of
+ * single random numbers from various Erlang distributions.
+ *
+ * The Erlang distribution is a special case of the Gamma distribution where k
+ * (= alpha) is a non-negative integer. Erlang distributed variables can be
+ * generated using a much faster algorithm than gamma variables.
+ *
+ * The probability density function is defined over the interval [0,\f$+\infty\f$) as:
+ * \f$ \frac{x^{k-1} e^{-\frac{x}{\lambda}}}{\lambda^k (k-1)!}\f$
+ * where \f$ mean = k \lambda \f$ and
+ * \f$ variance = k \lambda^2\f$
+ *
+ * Here is an example of how to use this class:
+ * \code
+ * uint32_t k = 5;
+ * double lambda = 2.0;
+ *
+ * Ptr<ErlangRandomVariable> x = CreateObject<ErlangRandomVariable> ();
+ * x->SetAttribute ("K", IntegerValue (k));
+ * x->SetAttribute ("Lambda", DoubleValue (lambda));
+ *
+ * // The expected value for the mean of the values returned by a
+ * // Erlangly distributed random variable is equal to
+ * //
+ * // E[value] = k * lambda .
+ * //
+ * double value = x->GetValue ();
+ * \endcode
+ */
+class ErlangRandomVariable : public RandomVariableStream
+{
+public:
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Creates an Erlang distribution RNG with the default values
+ * for k and lambda.
+ */
+ ErlangRandomVariable ();
+
+ /**
+ * \brief Returns the k value for the Erlang distribution returned by this RNG stream.
+ * \return The k value for the Erlang distribution returned by this RNG stream.
+ */
+ uint32_t GetK (void) const;
+
+ /**
+ * \brief Returns the lambda value for the Erlang distribution returned by this RNG stream.
+ * \return The lambda value for the Erlang distribution returned by this RNG stream.
+ */
+ double GetLambda (void) const;
+
+ /**
+ * \brief Returns a random double from an Erlang distribution with the specified k and lambda.
+ * \param k K value for the Erlang distribution.
+ * \param lambda Lambda value for the Erlang distribution.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ */
+ double GetValue (uint32_t k, double lambda);
+
+ /**
+ * \brief Returns a random unsigned integer from an Erlang distribution with the specified k and lambda.
+ * \param k K value for the Erlang distribution.
+ * \param lambda Lambda value for the Erlang distribution.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ */
+ uint32_t GetInteger (uint32_t k, uint32_t lambda);
+
+ /**
+ * \brief Returns a random double from an Erlang distribution with the current k and lambda.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ *
+ * Note that we have to re-implement this method here because the method is
+ * overloaded above for the two-argument variant and the c++ name resolution
+ * rules don't work well with overloads split between parent and child
+ * classes.
+ */
+ virtual double GetValue (void);
+
+ /**
+ * \brief Returns a random unsigned integer from an Erlang distribution with the current k and lambda.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ */
+ virtual uint32_t GetInteger (void);
+
+private:
+ /**
+ * \brief Returns a random double from an exponential distribution with the specified mean and upper bound.
+ * \param mean Mean value of the random variables.
+ * \param bound Upper bound on values returned.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$u\f$ is a uniform variable
+ * over [0,1] and
+ *
+ * \f[
+ * x = - mean * \log(u)
+ * \f]
+ *
+ * is a value that would be returned normally, then \f$(1 - u\f$) is
+ * the distance that \f$u\f$ would be from \f$1\f$. The value
+ * returned in the antithetic case, \f$x'\f$, is calculated as
+ *
+ * \f[
+ * x' = - mean * \log(1 - u),
+ * \f]
+ *
+ * which now involves the log of the distance \f$u\f$ is from the 1.
+ */
+ double GetExponentialValue (double mean, double bound);
+
+ /// The k value for the Erlang distribution returned by this RNG stream.
+ uint32_t m_k;
+
+ /// The lambda value for the Erlang distribution returned by this RNG stream.
+ double m_lambda;
+
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The triangular distribution Random Number Generator (RNG) that
+ * allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed triangular distribution. It also supports the generation of
+ * single random numbers from various triangular distributions.
+ *
+ * This distribution is a triangular distribution. The probability density
+ * is in the shape of a triangle.
+ *
+ * Here is an example of how to use this class:
+ * \code
+ * double mean = 5.0;
+ * double min = 2.0;
+ * double max = 10.0;
+ *
+ * Ptr<TriangularRandomVariable> x = CreateObject<TriangularRandomVariable> ();
+ * x->SetAttribute ("Mean", DoubleValue (mean));
+ * x->SetAttribute ("Min", DoubleValue (min));
+ * x->SetAttribute ("Max", DoubleValue (max));
+ *
+ * // The expected value for the mean of the values returned by a
+ * // triangularly distributed random variable is equal to mean.
+ * double value = x->GetValue ();
+ * \endcode
+ */
+class TriangularRandomVariable : public RandomVariableStream
+{
+public:
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Creates a triangular distribution RNG with the default
+ * values for the mean, lower bound, and upper bound.
+ */
+ TriangularRandomVariable ();
+
+ /**
+ * \brief Returns the mean value for the triangular distribution returned by this RNG stream.
+ * \return The mean value for the triangular distribution returned by this RNG stream.
+ */
+ double GetMean (void) const;
+
+ /**
+ * \brief Returns the lower bound for the triangular distribution returned by this RNG stream.
+ * \return The lower bound for the triangular distribution returned by this RNG stream.
+ */
+ double GetMin (void) const;
+
+ /**
+ * \brief Returns the upper bound on values that can be returned by this RNG stream.
+ * \return The upper bound on values that can be returned by this RNG stream.
+ */
+ double GetMax (void) const;
+
+ /**
+ * \brief Returns a random double from a triangular distribution with the specified mean, min, and max.
+ * \param mean Mean value for the triangular distribution.
+ * \param min Low end of the range.
+ * \param max High end of the range.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$u\f$ is a uniform variable
+ * over [0,1] and
+ *
+ * \f[
+ * x = \left\{ \begin{array}{rl}
+ * min + \sqrt{u * (max - min) * (mode - min)} &\mbox{ if $u <= (mode - min)/(max - min)$} \\
+ * max - \sqrt{ (1 - u) * (max - min) * (max - mode) } &\mbox{ otherwise}
+ * \end{array} \right.
+ * \f]
+ *
+ * is a value that would be returned normally, where the mode or
+ * peak of the triangle is calculated as
+ *
+ * \f[
+ * mode = 3.0 * mean - min - max .
+ * \f]
+ *
+ * Then, \f$(1 - u\f$) is the distance that \f$u\f$ would be from
+ * \f$1\f$. The value returned in the antithetic case, \f$x'\f$, is
+ * calculated as
+ *
+ * \f[
+ * x' = \left\{ \begin{array}{rl}
+ * min + \sqrt{(1 - u) * (max - min) * (mode - min)} &\mbox{ if $(1 - u) <= (mode - min)/(max - min)$} \\
+ * max - \sqrt{ u * (max - min) * (max - mode) } &\mbox{ otherwise}
+ * \end{array} \right.
+ * \f]
+ *
+ * which now involves the distance \f$u\f$ is from the 1.
+ */
+ double GetValue (double mean, double min, double max);
+
+ /**
+ * \brief Returns a random unsigned integer from a triangular distribution with the specified mean, min, and max.
+ * \param mean Mean value for the triangular distribution.
+ * \param min Low end of the range.
+ * \param max High end of the range.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$u\f$ is a uniform variable
+ * over [0,1] and
+ *
+ * \f[
+ * x = \left\{ \begin{array}{rl}
+ * min + \sqrt{u * (max - min) * (mode - min)} &\mbox{ if $u <= (mode - min)/(max - min)$} \\
+ * max - \sqrt{ (1 - u) * (max - min) * (max - mode) } &\mbox{ otherwise}
+ * \end{array} \right.
+ * \f]
+ *
+ * is a value that would be returned normally, where the mode or
+ * peak of the triangle is calculated as
+ *
+ * \f[
+ * mode = 3.0 * mean - min - max .
+ * \f]
+ *
+ * Then, \f$(1 - u\f$) is the distance that \f$u\f$ would be from
+ * \f$1\f$. The value returned in the antithetic case, \f$x'\f$, is
+ * calculated as
+ *
+ * \f[
+ * x' = \left\{ \begin{array}{rl}
+ * min + \sqrt{(1 - u) * (max - min) * (mode - min)} &\mbox{ if $(1 - u) <= (mode - min)/(max - min)$} \\
+ * max - \sqrt{ u * (max - min) * (max - mode) } &\mbox{ otherwise}
+ * \end{array} \right.
+ * \f]
+ *
+ * which now involves the distance \f$u\f$ is from the 1.
+ */
+ uint32_t GetInteger (uint32_t mean, uint32_t min, uint32_t max);
+
+ /**
+ * \brief Returns a random double from a triangular distribution with the current mean, min, and max.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$u\f$ is a uniform variable
+ * over [0,1] and
+ *
+ * \f[
+ * x = \left\{ \begin{array}{rl}
+ * min + \sqrt{u * (max - min) * (mode - min)} &\mbox{ if $u <= (mode - min)/(max - min)$} \\
+ * max - \sqrt{ (1 - u) * (max - min) * (max - mode) } &\mbox{ otherwise}
+ * \end{array} \right.
+ * \f]
+ *
+ * is a value that would be returned normally, where the mode or
+ * peak of the triangle is calculated as
+ *
+ * \f[
+ * mode = 3.0 * mean - min - max .
+ * \f]
+ *
+ * Then, \f$(1 - u\f$) is the distance that \f$u\f$ would be from
+ * \f$1\f$. The value returned in the antithetic case, \f$x'\f$, is
+ * calculated as
+ *
+ * \f[
+ * x' = \left\{ \begin{array}{rl}
+ * min + \sqrt{(1 - u) * (max - min) * (mode - min)} &\mbox{ if $(1 - u) <= (mode - min)/(max - min)$} \\
+ * max - \sqrt{ u * (max - min) * (max - mode) } &\mbox{ otherwise}
+ * \end{array} \right.
+ * \f]
+ *
+ * which now involves the distance \f$u\f$ is from the 1.
+ *
+ * Note that we have to re-implement this method here because the method is
+ * overloaded above for the three-argument variant and the c++ name resolution
+ * rules don't work well with overloads split between parent and child
+ * classes.
+ */
+ virtual double GetValue (void);
+
+ /**
+ * \brief Returns a random unsigned integer from a triangular distribution with the current mean, min, and max.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if
+ * m_isAntithetic is equal to true. If \f$u\f$ is a uniform variable
+ * over [0,1] and
+ *
+ * \f[
+ * x = \left\{ \begin{array}{rl}
+ * min + \sqrt{u * (max - min) * (mode - min)} &\mbox{ if $u <= (mode - min)/(max - min)$} \\
+ * max - \sqrt{ (1 - u) * (max - min) * (max - mode) } &\mbox{ otherwise}
+ * \end{array} \right.
+ * \f]
+ *
+ * is a value that would be returned normally, where the mode or
+ * peak of the triangle is calculated as
+ *
+ * \f[
+ * mode = 3.0 * mean - min - max .
+ * \f]
+ *
+ * Then, \f$(1 - u\f$) is the distance that \f$u\f$ would be from
+ * \f$1\f$. The value returned in the antithetic case, \f$x'\f$, is
+ * calculated as
+ *
+ * \f[
+ * x' = \left\{ \begin{array}{rl}
+ * min + \sqrt{(1 - u) * (max - min) * (mode - min)} &\mbox{ if $(1 - u) <= (mode - min)/(max - min)$} \\
+ * max - \sqrt{ u * (max - min) * (max - mode) } &\mbox{ otherwise}
+ * \end{array} \right.
+ * \f]
+ *
+ * which now involves the distance \f$u\f$ is from the 1.
+ */
+ virtual uint32_t GetInteger (void);
+
+private:
+ /// The mean value for the triangular distribution returned by this RNG stream.
+ double m_mean;
+
+ /// The lower bound on values that can be returned by this RNG stream.
+ double m_min;
+
+ /// The upper bound on values that can be returned by this RNG stream.
+ double m_max;
+
+ /// It's easier to work with the mode internally instead of the
+ /// mean. They are related by the simple: mean = (min+max+mode)/3.
+ double m_mode;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The Zipf distribution Random Number Generator (RNG) that
+ * allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed Zipf distribution. It also supports the generation of
+ * single random numbers from various Zipf distributions.
+ *
+ * The Zipf's law states that given some corpus of natural language
+ * utterances, the frequency of any word is inversely proportional
+ * to its rank in the frequency table.
+ *
+ * Zipf's distribution has two parameters, alpha and N, where:
+ * \f$ \alpha > 0 \f$ (real) and \f$ N \in \{1,2,3 \dots\}\f$ (integer).
+ * Probability Mass Function is \f$ f(k; \alpha, N) = k^{-\alpha}/ H_{N,\alpha} \f$
+ * where \f$ H_{N,\alpha} = \sum_{m=1}^N m^{-\alpha} \f$
+ *
+ * Here is an example of how to use this class:
+ * \code
+ * uint32_t n = 1;
+ * double alpha = 2.0;
+ *
+ * Ptr<ZipfRandomVariable> x = CreateObject<ZipfRandomVariable> ();
+ * x->SetAttribute ("N", IntegerValue (n));
+ * x->SetAttribute ("Alpha", DoubleValue (alpha));
+ *
+ * // The expected value for the mean of the values returned by a
+ * // Zipfly distributed random variable is equal to
+ * //
+ * // H
+ * // N, alpha - 1
+ * // E[value] = ---------------
+ * // H
+ * // N, alpha
+ * //
+ * // where
+ * //
+ * // N
+ * // ---
+ * // \ -alpha
+ * // H = / m .
+ * // N, alpha ---
+ * // m=1
+ * //
+ * // For this test,
+ * //
+ * // -(alpha - 1)
+ * // 1
+ * // E[value] = ---------------
+ * // -alpha
+ * // 1
+ * //
+ * // = 1 .
+ * //
+ * double value = x->GetValue ();
+ * \endcode
+ */
+class ZipfRandomVariable : public RandomVariableStream
+{
+public:
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Creates a Zipf distribution RNG with the default values
+ * for n and alpha.
+ */
+ ZipfRandomVariable ();
+
+ /**
+ * \brief Returns the n value for the Zipf distribution returned by this RNG stream.
+ * \return The n value for the Zipf distribution returned by this RNG stream.
+ */
+ uint32_t GetN (void) const;
+
+ /**
+ * \brief Returns the alpha value for the Zipf distribution returned by this RNG stream.
+ * \return The alpha value for the Zipf distribution returned by this RNG stream.
+ */
+ double GetAlpha (void) const;
+
+ /**
+ * \brief Returns a random double from a Zipf distribution with the specified n and alpha.
+ * \param n N value for the Zipf distribution.
+ * \param alpha Alpha value for the Zipf distribution.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ */
+ double GetValue (uint32_t n, double alpha);
+
+ /**
+ * \brief Returns a random unsigned integer from a Zipf distribution with the specified n and alpha.
+ * \param n N value for the Zipf distribution.
+ * \param alpha Alpha value for the Zipf distribution.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ */
+ uint32_t GetInteger (uint32_t n, uint32_t alpha);
+
+ /**
+ * \brief Returns a random double from a Zipf distribution with the current n and alpha.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ *
+ * Note that we have to re-implement this method here because the method is
+ * overloaded above for the two-argument variant and the c++ name resolution
+ * rules don't work well with overloads split between parent and child
+ * classes.
+ */
+ virtual double GetValue (void);
+
+ /**
+ * \brief Returns a random unsigned integer from a Zipf distribution with the current n and alpha.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ */
+ virtual uint32_t GetInteger (void);
+
+private:
+ /// The n value for the Zipf distribution returned by this RNG stream.
+ uint32_t m_n;
+
+ /// The alpha value for the Zipf distribution returned by this RNG stream.
+ double m_alpha;
+
+ /// The normalization constant.
+ double m_c;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The zeta distribution Random Number Generator (RNG) that
+ * allows stream numbers to be set deterministically.
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed zeta distribution. It also supports the generation of
+ * single random numbers from various zeta distributions.
+ *
+ * The Zeta distribution is closely related to Zipf distribution when
+ * N goes to infinity.
+ *
+ * Zeta distribution has one parameter, alpha, \f$ \alpha > 1 \f$ (real).
+ * Probability Mass Function is \f$ f(k; \alpha) = k^{-\alpha}/\zeta(\alpha) \f$
+ * where \f$ \zeta(\alpha) \f$ is the Riemann zeta function ( \f$ \sum_{n=1}^\infty n^{-\alpha} ) \f$
+ *
+ * Here is an example of how to use this class:
+ * \code
+ * double alpha = 2.0;
+ *
+ * Ptr<ZetaRandomVariable> x = CreateObject<ZetaRandomVariable> ();
+ * x->SetAttribute ("Alpha", DoubleValue (alpha));
+ *
+ * // The expected value for the mean of the values returned by a
+ * // zetaly distributed random variable is equal to
+ * //
+ * // zeta(alpha - 1)
+ * // E[value] = --------------- for alpha > 2 ,
+ * // zeta(alpha)
+ * //
+ * // where zeta(alpha) is the Riemann zeta function.
+ * //
+ * // There are no simple analytic forms for the Riemann zeta
+ * // function, which is the reason the known mean of the values
+ * // cannot be calculated in this example.
+ * //
+ * double value = x->GetValue ();
+ * \endcode
+ */
+class ZetaRandomVariable : public RandomVariableStream
+{
+public:
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Creates a zeta distribution RNG with the default value for
+ * alpha.
+ */
+ ZetaRandomVariable ();
+
+ /**
+ * \brief Returns the alpha value for the zeta distribution returned by this RNG stream.
+ * \return The alpha value for the zeta distribution returned by this RNG stream.
+ */
+ double GetAlpha (void) const;
+
+ /**
+ * \brief Returns a random double from a zeta distribution with the specified alpha.
+ * \param alpha Alpha value for the zeta distribution.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ */
+ double GetValue (double alpha);
+
+ /**
+ * \brief Returns a random unsigned integer from a zeta distribution with the specified alpha.
+ * \param alpha Alpha value for the zeta distribution.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ */
+ uint32_t GetInteger (uint32_t alpha);
+
+ /**
+ * \brief Returns a random double from a zeta distribution with the current alpha.
+ * \return A floating point random value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ *
+ * Note that we have to re-implement this method here because the method is
+ * overloaded above for the two-argument variant and the c++ name resolution
+ * rules don't work well with overloads split between parent and child
+ * classes.
+ */
+ virtual double GetValue (void);
+
+ /**
+ * \brief Returns a random unsigned integer from a zeta distribution with the current alpha.
+ * \return A random unsigned integer value.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ */
+ virtual uint32_t GetInteger (void);
+
+private:
+ /// The alpha value for the zeta distribution returned by this RNG stream.
+ double m_alpha;
+
+ /// Just for calculus simplifications.
+ double m_b;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The Random Number Generator (RNG) that returns a predetermined sequence.
+ *
+ * Defines a random variable that has a specified, predetermined
+ * sequence. This would be useful when trying to force the RNG to
+ * return a known sequence, perhaps to compare NS-3 to some other
+ * simulator
+ *
+ * Creates a generator that returns successive elements of the values
+ * array on successive calls to RandomVariableStream::GetValue. Note
+ * that the values in the array are copied and stored by the generator
+ * (deep-copy). Also note that the sequence repeats if more values
+ * are requested than are present in the array.
+ *
+ * Here is an example of how to use this class:
+ * \code
+ * Ptr<DeterministicRandomVariable> s = CreateObject<DeterministicRandomVariable> ();
+ *
+ * // The following array should give the sequence
+ * //
+ * // 4, 4, 7, 7, 10, 10 .
+ * //
+ * double array [] = { 4, 4, 7, 7, 10, 10};
+ * uint64_t count = 6;
+ * s->SetValueArray (array, count);
+ *
+ * double value = x->GetValue ();
+ * \endcode
+ */
+class DeterministicRandomVariable : public RandomVariableStream
+{
+public:
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Creates a deterministic RNG that will have a predetermined
+ * sequence of values.
+ */
+ DeterministicRandomVariable ();
+ virtual ~DeterministicRandomVariable ();
+
+ /**
+ * \brief Sets the array of values that holds the predetermined sequence.
+ * \param values Array of random values to return in sequence.
+ * \param length Number of values in the array.
+ *
+ * Note that the values in the array are copied and stored
+ * (deep-copy).
+ */
+ void SetValueArray (double* values, uint64_t length);
+
+ /**
+ * \brief Returns the next value in the sequence.
+ * \return The floating point next value in the sequence.
+ */
+ virtual double GetValue (void);
+
+ /**
+ * \brief Returns the next value in the sequence.
+ * \return The integer next value in the sequence.
+ */
+ virtual uint32_t GetInteger (void);
+
+private:
+ /// Position in the array of values.
+ uint64_t m_count;
+
+ /// Position of the next value in the array of values.
+ uint64_t m_next;
+
+ /// Array of values to return in sequence.
+ double* m_data;
+};
+
+/**
+ * \ingroup randomvariable
+ * \brief The Random Number Generator (RNG) that has a specified empirical distribution.
+ *
+ * Defines a random variable that has a specified, empirical
+ * distribution. The distribution is specified by a
+ * series of calls to the CDF member function, specifying a
+ * value and the probability that the function value is less than
+ * the specified value. When values are requested,
+ * a uniform random variable is used to select a probability,
+ * and the return value is interpreted linearly between the
+ * two appropriate points in the CDF. The method is known
+ * as inverse transform sampling:
+ * (http://en.wikipedia.org/wiki/Inverse_transform_sampling).
+ *
+ * Here is an example of how to use this class:
+ * \code
+ * // Create the RNG with a uniform distribution between 0 and 10.
+ * Ptr<EmpiricalRandomVariable> x = CreateObject<EmpiricalRandomVariable> ();
+ * x->CDF ( 0.0, 0.0);
+ * x->CDF ( 5.0, 0.5);
+ * x->CDF (10.0, 1.0);
+ *
+ * // The expected value for the mean of the values returned by this
+ * // empirical distribution is the midpoint of the distribution
+ * //
+ * // E[value] = 5 .
+ * //
+ * double value = x->GetValue ();
+ * \endcode
+ */
+class EmpiricalRandomVariable : public RandomVariableStream
+{
+public:
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Creates an empirical RNG that has a specified, empirical
+ * distribution.
+ */
+ EmpiricalRandomVariable ();
+
+ /**
+ * \brief Specifies a point in the empirical distribution
+ * \param v The function value for this point
+ * \param c Probability that the function is less than or equal to v
+ */
+ void CDF (double v, double c); // Value, prob <= Value
+
+ /**
+ * \brief Returns the next value in the empirical distribution.
+ * \return The floating point next value in the empirical distribution.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ */
+ virtual double GetValue (void);
+
+ /**
+ * \brief Returns the next value in the empirical distribution.
+ * \return The integer next value in the empirical distribution.
+ *
+ * Note that antithetic values are being generated if m_isAntithetic
+ * is equal to true. If \f$u\f$ is a uniform variable over [0,1]
+ * and \f$x\f$ is a value that would be returned normally, then
+ * \f$(1 - u\f$) is the distance that \f$u\f$ would be from \f$1\f$.
+ * The value returned in the antithetic case, \f$x'\f$, uses (1-u),
+ * which is the distance \f$u\f$ is from the 1.
+ */
+ virtual uint32_t GetInteger (void);
+
+private:
+ class ValueCDF
+ {
+public:
+ ValueCDF ();
+ ValueCDF (double v, double c);
+ ValueCDF (const ValueCDF& c);
+ double value;
+ double cdf;
+ };
+ virtual void Validate (); // Insure non-decreasing emiprical values
+ virtual double Interpolate (double, double, double, double, double);
+ bool validated; // True if non-decreasing validated
+ std::vector<ValueCDF> emp; // Empicical CDF
+};
+
+} // namespace ns3
+
+#endif /* RANDOM_VARIABLE_STREAM_H */
--- a/src/core/model/random-variable.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/core/model/random-variable.cc Tue Jul 31 19:18:23 2012 +0200
@@ -33,9 +33,8 @@
#include <vector>
#include "assert.h"
-#include "config.h"
-#include "integer.h"
#include "random-variable.h"
+#include "rng-seed-manager.h"
#include "rng-stream.h"
#include "fatal-error.h"
@@ -44,44 +43,6 @@
namespace ns3 {
// -----------------------------------------------------------------------------
-// Seed Manager
-// -----------------------------------------------------------------------------
-
-uint32_t SeedManager::GetSeed ()
-{
- uint32_t s[6];
- RngStream::GetPackageSeed (s);
- NS_ASSERT (
- s[0] == s[1]
- && s[0] == s[2]
- && s[0] == s[3]
- && s[0] == s[4]
- && s[0] == s[5]
- );
- return s[0];
-}
-
-void SeedManager::SetSeed (uint32_t seed)
-{
- Config::SetGlobal ("RngSeed", IntegerValue (seed));
-}
-
-void SeedManager::SetRun (uint32_t run)
-{
- Config::SetGlobal ("RngRun", IntegerValue (run));
-}
-
-uint32_t SeedManager::GetRun ()
-{
- return RngStream::GetPackageRun ();
-}
-
-bool SeedManager::CheckSeed (uint32_t seed)
-{
- return RngStream::CheckSeed (seed);
-}
-
-// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// RandomVariableBase methods
@@ -95,22 +56,24 @@
virtual double GetValue () = 0;
virtual uint32_t GetInteger ();
virtual RandomVariableBase* Copy (void) const = 0;
-
-protected:
+ RngStream *GetStream(void);
+private:
RngStream* m_generator; // underlying generator being wrapped
};
RandomVariableBase::RandomVariableBase ()
- : m_generator (NULL)
+ : m_generator (0)
{
}
RandomVariableBase::RandomVariableBase (const RandomVariableBase& r)
: m_generator (0)
{
- if (r.m_generator)
+ if (r.m_generator != 0)
{
- m_generator = new RngStream (*r.m_generator);
+ m_generator = new RngStream (RngSeedManager::GetSeed (),
+ RngSeedManager::GetNextStreamIndex (),
+ RngSeedManager::GetRun ());
}
}
@@ -124,6 +87,18 @@
return (uint32_t)GetValue ();
}
+RngStream *
+RandomVariableBase::GetStream (void)
+{
+ if (m_generator == 0)
+ {
+ m_generator = new RngStream (RngSeedManager::GetSeed (),
+ RngSeedManager::GetNextStreamIndex (),
+ RngSeedManager::GetRun ());
+ }
+ return m_generator;
+}
+
// -------------------------------------------------------
RandomVariable::RandomVariable ()
@@ -250,20 +225,14 @@
double UniformVariableImpl::GetValue ()
{
- if (!m_generator)
- {
- m_generator = new RngStream ();
- }
- return m_min + m_generator->RandU01 () * (m_max - m_min);
+ RngStream *generator = GetStream ();
+ return m_min + generator->RandU01 () * (m_max - m_min);
}
double UniformVariableImpl::GetValue (double s, double l)
{
- if (!m_generator)
- {
- m_generator = new RngStream ();
- }
- return s + m_generator->RandU01 () * (l - s);
+ RngStream *generator = GetStream ();
+ return s + generator->RandU01 () * (l - s);
}
RandomVariableBase* UniformVariableImpl::Copy () const
@@ -573,13 +542,10 @@
double ExponentialVariableImpl::GetValue ()
{
- if (!m_generator)
- {
- m_generator = new RngStream ();
- }
+ RngStream *generator = GetStream ();
while (1)
{
- double r = -m_mean*log (m_generator->RandU01 ());
+ double r = -m_mean*log (generator->RandU01 ());
if (m_bound == 0 || r <= m_bound)
{
return r;
@@ -737,13 +703,10 @@
double ParetoVariableImpl::GetValue ()
{
- if (!m_generator)
- {
- m_generator = new RngStream ();
- }
+ RngStream *generator = GetStream ();
while (1)
{
- double r = (m_scale * ( 1.0 / pow (m_generator->RandU01 (), 1.0 / m_shape)));
+ double r = (m_scale * ( 1.0 / pow (generator->RandU01 (), 1.0 / m_shape)));
if (m_bound == 0 || r <= m_bound)
{
return r;
@@ -871,14 +834,11 @@
double WeibullVariableImpl::GetValue ()
{
- if (!m_generator)
- {
- m_generator = new RngStream ();
- }
+ RngStream *generator = GetStream ();
double exponent = 1.0 / m_alpha;
while (1)
{
- double r = m_mean * pow ( -log (m_generator->RandU01 ()), exponent);
+ double r = m_mean * pow ( -log (generator->RandU01 ()), exponent);
if (m_bound == 0 || r <= m_bound)
{
return r;
@@ -981,10 +941,7 @@
double NormalVariableImpl::GetValue ()
{
- if (!m_generator)
- {
- m_generator = new RngStream ();
- }
+ RngStream *generator = GetStream ();
if (m_nextValid)
{ // use previously generated
m_nextValid = false;
@@ -994,8 +951,8 @@
{ // See Simulation Modeling and Analysis p. 466 (Averill Law)
// for algorithm; basically a Box-Muller transform:
// http://en.wikipedia.org/wiki/Box-Muller_transform
- double u1 = m_generator->RandU01 ();
- double u2 = m_generator->RandU01 ();
+ double u1 = generator->RandU01 ();
+ double u2 = generator->RandU01 ();
double v1 = 2 * u1 - 1;
double v2 = 2 * u2 - 1;
double w = v1 * v1 + v2 * v2;
@@ -1138,10 +1095,7 @@
double EmpiricalVariableImpl::GetValue ()
{ // Return a value from the empirical distribution
// This code based (loosely) on code by Bruce Mah (Thanks Bruce!)
- if (!m_generator)
- {
- m_generator = new RngStream ();
- }
+ RngStream *generator = GetStream ();
if (emp.size () == 0)
{
return 0.0; // HuH? No empirical data
@@ -1150,7 +1104,7 @@
{
Validate (); // Insure in non-decreasing
}
- double r = m_generator->RandU01 ();
+ double r = generator->RandU01 ();
if (r <= emp.front ().cdf)
{
return emp.front ().value; // Less than first
@@ -1406,18 +1360,15 @@
double
LogNormalVariableImpl::GetValue ()
{
- if (!m_generator)
- {
- m_generator = new RngStream ();
- }
+ RngStream *generator = GetStream ();
double u, v, r2, normal, z;
do
{
/* choose x,y in uniform square (-1,-1) to (+1,+1) */
- u = -1 + 2 * m_generator->RandU01 ();
- v = -1 + 2 * m_generator->RandU01 ();
+ u = -1 + 2 * generator->RandU01 ();
+ v = -1 + 2 * generator->RandU01 ();
/* see if it is in the unit circle */
r2 = u * u + v * v;
@@ -1504,14 +1455,11 @@
double
GammaVariableImpl::GetValue (double alpha, double beta)
{
- if (!m_generator)
- {
- m_generator = new RngStream ();
- }
+ RngStream *generator = GetStream ();
if (alpha < 1)
{
- double u = m_generator->RandU01 ();
+ double u = generator->RandU01 ();
return GetValue (1.0 + alpha, beta) * pow (u, 1.0 / alpha);
}
@@ -1529,7 +1477,7 @@
while (v <= 0);
v = v * v * v;
- u = m_generator->RandU01 ();
+ u = generator->RandU01 ();
if (u < 1 - 0.0331 * x * x * x * x)
{
break;
@@ -1627,11 +1575,8 @@
double
ErlangVariableImpl::GetValue (unsigned int k, double lambda)
{
- if (!m_generator)
- {
- m_generator = new RngStream ();
- }
-
+ // XXX: Fixme: do not create a new
+ // RNG stream every time the function is called !
ExponentialVariable exponential (lambda);
double result = 0;
@@ -1723,11 +1668,8 @@
double TriangularVariableImpl::GetValue ()
{
- if (!m_generator)
- {
- m_generator = new RngStream ();
- }
- double u = m_generator->RandU01 ();
+ RngStream *generator = GetStream ();
+ double u = generator->RandU01 ();
if (u <= (m_mode - m_min) / (m_max - m_min) )
{
return m_min + sqrt (u * (m_max - m_min) * (m_mode - m_min) );
@@ -1811,12 +1753,9 @@
double
ZipfVariableImpl::GetValue ()
{
- if (!m_generator)
- {
- m_generator = new RngStream ();
- }
+ RngStream *generator = GetStream ();
- double u = m_generator->RandU01 ();
+ double u = generator->RandU01 ();
double sum_prob = 0,zipf_value = 0;
for (int i = 1; i <= m_n; i++)
{
@@ -1895,10 +1834,7 @@
double
ZetaVariableImpl::GetValue ()
{
- if (!m_generator)
- {
- m_generator = new RngStream ();
- }
+ RngStream *generator = GetStream ();
double u, v;
double X, T;
@@ -1906,8 +1842,8 @@
do
{
- u = m_generator->RandU01 ();
- v = m_generator->RandU01 ();
+ u = generator->RandU01 ();
+ v = generator->RandU01 ();
X = floor (pow (u, -1.0 / (m_alpha - 1.0)));
T = pow (1.0 + 1.0 / X, m_alpha - 1.0);
test = v * X * (T - 1.0) / (m_b - 1.0);
--- a/src/core/model/random-variable.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/core/model/random-variable.h Tue Jul 31 19:18:23 2012 +0200
@@ -29,6 +29,7 @@
#include <ostream>
#include "attribute.h"
#include "attribute-helper.h"
+#include "rng-seed-manager.h"
/**
* \ingroup core
@@ -40,69 +41,6 @@
class RandomVariableBase;
-class SeedManager
-{
-public:
- /**
- * \brief set the seed
- * it will duplicate the seed value 6 times
- * \code
- * SeedManger::SetSeed(15);
- * UniformVariable x(2,3); //these will give the same output everytime
- * ExponentialVariable y(120); //as long as the seed stays the same
- * \endcode
- * \param seed
- *
- * Note, while the underlying RNG takes six integer values as a seed;
- * it is sufficient to set these all to the same integer, so we provide
- * a simpler interface here that just takes one integer.
- */
- static void SetSeed (uint32_t seed);
-
- /**
- * \brief Get the seed value
- * \return the seed value
- *
- * Note: returns the first of the six seed values used in the underlying RNG
- */
- static uint32_t GetSeed ();
-
- /**
- * \brief Set the run number of simulation
- *
- * \code
- * SeedManager::SetSeed(12);
- * int N = atol(argv[1]); //read in run number from command line
- * SeedManager::SetRun(N);
- * UniformVariable x(0,10);
- * ExponentialVariable y(2902);
- * \endcode
- * In this example, N could successivly be equal to 1,2,3, etc. and the user
- * would continue to get independent runs out of the single simulation. For
- * this simple example, the following might work:
- * \code
- * ./simulation 0
- * ...Results for run 0:...
- *
- * ./simulation 1
- * ...Results for run 1:...
- * \endcode
- */
- static void SetRun (uint32_t run);
- /**
- * \returns the current run number
- * @sa SetRun
- */
- static uint32_t GetRun (void);
-
- /**
- * \brief Check if seed value is valid if wanted to be used as seed
- * \return true if valid and false if invalid
- */
- static bool CheckSeed (uint32_t seed);
-};
-
-
/**
* \brief The basic RNG for NS-3.
* \ingroup randomvariable
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/model/rng-seed-manager.cc Tue Jul 31 19:18:23 2012 +0200
@@ -0,0 +1,52 @@
+#include "rng-seed-manager.h"
+#include "global-value.h"
+#include "attribute-helper.h"
+#include "integer.h"
+#include "config.h"
+
+namespace ns3 {
+
+static uint64_t g_nextStreamIndex = 0;
+static ns3::GlobalValue g_rngSeed ("RngSeed",
+ "The global seed of all rng streams",
+ ns3::IntegerValue(1),
+ ns3::MakeIntegerChecker<uint32_t> ());
+static ns3::GlobalValue g_rngRun ("RngRun",
+ "The run number used to modify the global seed",
+ ns3::IntegerValue (1),
+ ns3::MakeIntegerChecker<int64_t> ());
+
+
+uint32_t RngSeedManager::GetSeed (void)
+{
+ IntegerValue seedValue;
+ g_rngSeed.GetValue (seedValue);
+ return seedValue.Get ();
+}
+void
+RngSeedManager::SetSeed (uint32_t seed)
+{
+ Config::SetGlobal ("RngSeed", IntegerValue(seed));
+}
+
+void RngSeedManager::SetRun (uint64_t run)
+{
+ Config::SetGlobal ("RngRun", IntegerValue (run));
+}
+
+uint64_t RngSeedManager::GetRun ()
+{
+ IntegerValue value;
+ g_rngRun.GetValue (value);
+ int run = value.Get();
+ return run;
+}
+
+uint64_t RngSeedManager::GetNextStreamIndex (void)
+{
+ uint64_t next = g_nextStreamIndex;
+ g_nextStreamIndex++;
+ return next;
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/model/rng-seed-manager.h Tue Jul 31 19:18:23 2012 +0200
@@ -0,0 +1,73 @@
+#ifndef RNG_SEED_MANAGER_H
+#define RNG_SEED_MANAGER_H
+
+#include <stdint.h>
+
+namespace ns3 {
+
+class RngSeedManager
+{
+public:
+ /**
+ * \brief set the seed
+ * it will duplicate the seed value 6 times
+ * \code
+ * SeedManger::SetSeed(15);
+ * UniformVariable x(2,3); //these will give the same output everytime
+ * ExponentialVariable y(120); //as long as the seed stays the same
+ * \endcode
+ * \param seed
+ *
+ * Note, while the underlying RNG takes six integer values as a seed;
+ * it is sufficient to set these all to the same integer, so we provide
+ * a simpler interface here that just takes one integer.
+ */
+ static void SetSeed (uint32_t seed);
+
+ /**
+ * \brief Get the seed value
+ * \return the seed value
+ *
+ * Note: returns the first of the six seed values used in the underlying RNG
+ */
+ static uint32_t GetSeed (void);
+
+ /**
+ * \brief Set the run number of simulation
+ *
+ * \code
+ * SeedManager::SetSeed(12);
+ * int N = atol(argv[1]); //read in run number from command line
+ * SeedManager::SetRun(N);
+ * UniformVariable x(0,10);
+ * ExponentialVariable y(2902);
+ * \endcode
+ * In this example, N could successivly be equal to 1,2,3, etc. and the user
+ * would continue to get independent runs out of the single simulation. For
+ * this simple example, the following might work:
+ * \code
+ * ./simulation 0
+ * ...Results for run 0:...
+ *
+ * ./simulation 1
+ * ...Results for run 1:...
+ * \endcode
+ */
+ static void SetRun (uint64_t run);
+ /**
+ * \returns the current run number
+ * @sa SetRun
+ */
+ static uint64_t GetRun (void);
+
+ static uint64_t GetNextStreamIndex(void);
+
+};
+
+// for compatibility
+typedef RngSeedManager SeedManager;
+
+} // namespace ns3
+
+
+#endif /* RNG_SEED_MANAGER_H */
--- a/src/core/model/rng-stream.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/core/model/rng-stream.cc Tue Jul 31 19:18:23 2012 +0200
@@ -15,18 +15,20 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
-// Modified for ns-3 by: Rajib Bhattacharjea<raj.b@gatech.edu>
+// Modified for ns-3 by:
+// - Rajib Bhattacharjea<raj.b@gatech.edu>
+// - Mathieu Lacage <mathieu.lacage@gmail.com>
//
#include <cstdlib>
#include <iostream>
#include "rng-stream.h"
-#include "global-value.h"
-#include "integer.h"
-using namespace std;
+#include "fatal-error.h"
namespace
{
+typedef double Matrix[3][3];
+
const double m1 = 4294967087.0;
const double m2 = 4294944443.0;
const double norm = 1.0 / (m1 + 1.0);
@@ -38,58 +40,30 @@
const double two53 = 9007199254740992.0;
const double fact = 5.9604644775390625e-8; /* 1 / 2^24 */
-// The following are the transition matrices of the two MRG components
-// (in matrix form), raised to the powers -1, 1, 2^76, and 2^127, resp.
-
-const double InvA1[3][3] = { // Inverse of A1p0
+const Matrix InvA1 = { // Inverse of A1p0
{ 184888585.0, 0.0, 1945170933.0 },
{ 1.0, 0.0, 0.0 },
{ 0.0, 1.0, 0.0 }
};
-const double InvA2[3][3] = { // Inverse of A2p0
+const Matrix InvA2 = { // Inverse of A2p0
{ 0.0, 360363334.0, 4225571728.0 },
{ 1.0, 0.0, 0.0 },
{ 0.0, 1.0, 0.0 }
};
-const double A1p0[3][3] = {
+const Matrix A1p0 = {
{ 0.0, 1.0, 0.0 },
{ 0.0, 0.0, 1.0 },
{ -810728.0, 1403580.0, 0.0 }
};
-const double A2p0[3][3] = {
+const Matrix A2p0 = {
{ 0.0, 1.0, 0.0 },
{ 0.0, 0.0, 1.0 },
{ -1370589.0, 0.0, 527612.0 }
};
-const double A1p76[3][3] = {
- { 82758667.0, 1871391091.0, 4127413238.0 },
- { 3672831523.0, 69195019.0, 1871391091.0 },
- { 3672091415.0, 3528743235.0, 69195019.0 }
-};
-
-const double A2p76[3][3] = {
- { 1511326704.0, 3759209742.0, 1610795712.0 },
- { 4292754251.0, 1511326704.0, 3889917532.0 },
- { 3859662829.0, 4292754251.0, 3708466080.0 }
-};
-
-const double A1p127[3][3] = {
- { 2427906178.0, 3580155704.0, 949770784.0 },
- { 226153695.0, 1230515664.0, 3580155704.0 },
- { 1988835001.0, 986791581.0, 1230515664.0 }
-};
-
-const double A2p127[3][3] = {
- { 1464411153.0, 277697599.0, 1610723613.0 },
- { 32183930.0, 1464411153.0, 1022607788.0 },
- { 2824425944.0, 32183930.0, 2093834863.0 }
-};
-
-
//-------------------------------------------------------------------------
// Return (a*s + c) MOD m; a, s, c and m must be < 2^35
@@ -101,16 +75,26 @@
v = a * s + c;
- if (v >= two53 || v <= -two53) {
- a1 = static_cast<int32_t> (a / two17); a -= a1 * two17;
+ if (v >= two53 || v <= -two53)
+ {
+ a1 = static_cast<int32_t> (a / two17);
+ a -= a1 * two17;
v = a1 * s;
- a1 = static_cast<int32_t> (v / m); v -= a1 * m;
+ a1 = static_cast<int32_t> (v / m);
+ v -= a1 * m;
v = v * two17 + a * s + c;
}
a1 = static_cast<int32_t> (v / m);
/* in case v < 0)*/
- if ((v -= a1 * m) < 0.0) return v += m; else return v;
+ if ((v -= a1 * m) < 0.0)
+ {
+ return v += m;
+ }
+ else
+ {
+ return v;
+ }
}
@@ -118,19 +102,22 @@
// Compute the vector v = A*s MOD m. Assume that -m < s[i] < m.
// Works also when v = s.
//
-void MatVecModM (const double A[3][3], const double s[3], double v[3],
+void MatVecModM (const Matrix A, const double s[3], double v[3],
double m)
{
int i;
double x[3]; // Necessary if v = s
- for (i = 0; i < 3; ++i) {
+ for (i = 0; i < 3; ++i)
+ {
x[i] = MultModM (A[i][0], s[0], 0.0, m);
x[i] = MultModM (A[i][1], s[1], x[i], m);
x[i] = MultModM (A[i][2], s[2], x[i], m);
}
for (i = 0; i < 3; ++i)
- v[i] = x[i];
+ {
+ v[i] = x[i];
+ }
}
@@ -138,41 +125,55 @@
// Compute the matrix C = A*B MOD m. Assume that -m < s[i] < m.
// Note: works also if A = C or B = C or A = B = C.
//
-void MatMatModM (const double A[3][3], const double B[3][3],
- double C[3][3], double m)
+void MatMatModM (const Matrix A, const Matrix B,
+ Matrix C, double m)
{
int i, j;
- double V[3], W[3][3];
+ double V[3];
+ Matrix W;
- for (i = 0; i < 3; ++i) {
+ for (i = 0; i < 3; ++i)
+ {
for (j = 0; j < 3; ++j)
- V[j] = B[j][i];
+ {
+ V[j] = B[j][i];
+ }
MatVecModM (A, V, V, m);
for (j = 0; j < 3; ++j)
- W[j][i] = V[j];
+ {
+ W[j][i] = V[j];
+ }
}
for (i = 0; i < 3; ++i)
- for (j = 0; j < 3; ++j)
- C[i][j] = W[i][j];
+ {
+ for (j = 0; j < 3; ++j)
+ {
+ C[i][j] = W[i][j];
+ }
+ }
}
//-------------------------------------------------------------------------
// Compute the matrix B = (A^(2^e) Mod m); works also if A = B.
//
-void MatTwoPowModM (const double A[3][3], double B[3][3], double m, int32_t e)
+void MatTwoPowModM (const Matrix src, Matrix dst, double m, int32_t e)
{
int i, j;
- /* initialize: B = A */
- if (A != B) {
- for (i = 0; i < 3; ++i)
- for (j = 0; j < 3; ++j)
- B[i][j] = A[i][j];
+ /* initialize: dst = src */
+ for (i = 0; i < 3; ++i)
+ {
+ for (j = 0; j < 3; ++j)
+ {
+ dst[i][j] = src[i][j];
+ }
}
- /* Compute B = A^(2^e) mod m */
+ /* Compute dst = src^(2^e) mod m */
for (i = 0; i < e; i++)
- MatMatModM (B, B, B, m);
+ {
+ MatMatModM (dst, dst, dst, m);
+ }
}
@@ -186,30 +187,60 @@
/* initialize: W = A; B = I */
for (i = 0; i < 3; ++i)
- for (j = 0; j < 3; ++j) {
- W[i][j] = A[i][j];
- B[i][j] = 0.0;
- }
+ {
+ for (j = 0; j < 3; ++j)
+ {
+ W[i][j] = A[i][j];
+ B[i][j] = 0.0;
+ }
+ }
for (j = 0; j < 3; ++j)
- B[j][j] = 1.0;
+ {
+ B[j][j] = 1.0;
+ }
/* Compute B = A^n mod m using the binary decomposition of n */
- while (n > 0) {
- if (n % 2) MatMatModM (W, B, B, m);
+ while (n > 0)
+ {
+ if (n % 2)
+ {
+ MatMatModM (W, B, B, m);
+ }
MatMatModM (W, W, W, m);
n /= 2;
}
}
-
-static ns3::GlobalValue g_rngSeed ("RngSeed",
- "The global seed of all rng streams",
- ns3::IntegerValue (1),
- ns3::MakeIntegerChecker<uint32_t> ());
-static ns3::GlobalValue g_rngRun ("RngRun",
- "The run number used to modify the global seed",
- ns3::IntegerValue (1),
- ns3::MakeIntegerChecker<uint32_t> ());
+// The following are the transition matrices of the two MRG components
+// (in matrix form), raised to all powers of 2 from 1 to 191
+struct Precalculated
+{
+ Matrix a1[190];
+ Matrix a2[190];
+};
+struct Precalculated PowerOfTwoConstants (void)
+{
+ struct Precalculated precalculated;
+ for (int i = 0; i < 190; i++)
+ {
+ int power = i + 1;
+ MatTwoPowModM (A1p0, precalculated.a1[i], m1, power);
+ MatTwoPowModM (A2p0, precalculated.a2[i], m2, power);
+ }
+ return precalculated;
+}
+void PowerOfTwoMatrix (int n, Matrix a1p, Matrix a2p)
+{
+ static struct Precalculated constants = PowerOfTwoConstants ();
+ for (int i = 0; i < 3; i ++)
+ {
+ for (int j = 0; j < 3; j++)
+ {
+ a1p[i][j] = constants.a1[n-1][i][j];
+ a2p[i][j] = constants.a2[n-1][i][j];
+ }
+ }
+}
} // end of anonymous namespace
@@ -218,348 +249,74 @@
//-------------------------------------------------------------------------
// Generate the next random number.
//
-double RngStream::U01 ()
+double RngStream::RandU01 ()
{
int32_t k;
double p1, p2, u;
/* Component 1 */
- p1 = a12 * Cg[1] - a13n * Cg[0];
+ p1 = a12 * m_currentState[1] - a13n * m_currentState[0];
k = static_cast<int32_t> (p1 / m1);
p1 -= k * m1;
- if (p1 < 0.0) p1 += m1;
- Cg[0] = Cg[1]; Cg[1] = Cg[2]; Cg[2] = p1;
+ if (p1 < 0.0)
+ {
+ p1 += m1;
+ }
+ m_currentState[0] = m_currentState[1]; m_currentState[1] = m_currentState[2]; m_currentState[2] = p1;
/* Component 2 */
- p2 = a21 * Cg[5] - a23n * Cg[3];
+ p2 = a21 * m_currentState[5] - a23n * m_currentState[3];
k = static_cast<int32_t> (p2 / m2);
p2 -= k * m2;
- if (p2 < 0.0) p2 += m2;
- Cg[3] = Cg[4]; Cg[4] = Cg[5]; Cg[5] = p2;
+ if (p2 < 0.0)
+ {
+ p2 += m2;
+ }
+ m_currentState[3] = m_currentState[4]; m_currentState[4] = m_currentState[5]; m_currentState[5] = p2;
/* Combination */
u = ((p1 > p2) ? (p1 - p2) * norm : (p1 - p2 + m1) * norm);
- return (anti == false) ? u : (1 - u);
-}
-
-
-//-------------------------------------------------------------------------
-// Generate the next random number with extended (53 bits) precision.
-//
-double RngStream::U01d ()
-{
- double u;
- u = U01 ();
- if (anti) {
- // Don't forget that U01() returns 1 - u in the antithetic case
- u += (U01 () - 1.0) * fact;
- return (u < 0.0) ? u + 1.0 : u;
- } else {
- u += U01 () * fact;
- return (u < 1.0) ? u : (u - 1.0);
- }
+ return u;
}
-//-------------------------------------------------------------------------
-// Check that the seeds are legitimate values. Returns true if legal seeds,
-// false otherwise.
-//
-bool RngStream::CheckSeed (const uint32_t seed[6])
-{
- int i;
-
- for (i = 0; i < 3; ++i) {
- if (seed[i] >= m1) {
- cerr << "****************************************\n\n"
- << "ERROR: Seed[" << i << "] >= 4294967087, Seed is not set."
- << "\n\n****************************************\n\n";
- return (false);
- }
- }
- for (i = 3; i < 6; ++i) {
- if (seed[i] >= m2) {
- cerr << "Seed[" << i << "] = " << seed[i] << endl;
- cerr << "*****************************************\n\n"
- << "ERROR: Seed[" << i << "] >= 4294944443, Seed is not set."
- << "\n\n*****************************************\n\n";
- return (false);
- }
- }
- if (seed[0] == 0 && seed[1] == 0 && seed[2] == 0) {
- cerr << "****************************\n\n"
- << "ERROR: First 3 seeds = 0.\n\n"
- << "****************************\n\n";
- return (false);
- }
- if (seed[3] == 0 && seed[4] == 0 && seed[5] == 0) {
- cerr << "****************************\n\n"
- << "ERROR: Last 3 seeds = 0.\n\n"
- << "****************************\n\n";
- return (false);
- }
- return true;
-}
-
-uint32_t
-RngStream::EnsureGlobalInitialized (void)
+RngStream::RngStream (uint32_t seedNumber, uint64_t stream, uint64_t substream)
{
- static bool initialized = false;
- static uint32_t run = 0;
- if (!initialized)
+ if (seedNumber >= m1 || seedNumber >= m2 || seedNumber == 0)
{
- initialized = true;
- uint32_t seed;
- IntegerValue value;
- g_rngSeed.GetValue (value);
- seed = value.Get ();
- g_rngRun.GetValue (value);
- run = value.Get ();
- SetPackageSeed (seed);
+ NS_FATAL_ERROR ("invalid Seed " << seedNumber);
}
- return run;
-}
-
-//*************************************************************************
-// Public members of the class start here
-
-
-//-------------------------------------------------------------------------
-// The default seed of the package; at run time, this will be overwritten
-// by the g_rngSeed value the first time RngStream::RngStream is visited;
-// so the value 12345 is for debugging
-//
-double RngStream::nextSeed[6] =
-{
- 12345.0, 12345.0, 12345.0, 12345.0, 12345.0, 12345.0
-};
-
-//-------------------------------------------------------------------------
-// constructor
-//
-RngStream::RngStream ()
-{
- uint32_t run = EnsureGlobalInitialized ();
-
- anti = false;
- incPrec = false;
- // Stream initialization moved to separate method.
- InitializeStream ();
- //move the state of this stream up
- ResetNthSubstream (run);
+ for (int i = 0; i < 6; ++i)
+ {
+ m_currentState[i] = seedNumber;
+ }
+ AdvanceNthBy (stream, 127, m_currentState);
+ AdvanceNthBy (substream, 76, m_currentState);
}
RngStream::RngStream(const RngStream& r)
{
- anti = r.anti;
- incPrec = r.incPrec;
- for (int i = 0; i < 6; ++i) {
- Cg[i] = r.Cg[i];
- Bg[i] = r.Bg[i];
- Ig[i] = r.Ig[i];
+ for (int i = 0; i < 6; ++i)
+ {
+ m_currentState[i] = r.m_currentState[i];
}
}
-
-void RngStream::InitializeStream ()
-{ // Moved from the RngStream constructor above to allow seeding
- // AFTER the global package seed has been set in the Random
- // object constructor.
- /* Information on a stream. The arrays {Cg, Bg, Ig} contain the current
- state of the stream, the starting state of the current SubStream, and the
- starting state of the stream. This stream generates antithetic variates
- if anti = true. It also generates numbers with extended precision (53
- bits if machine follows IEEE 754 standard) if incPrec = true. nextSeed
- will be the seed of the next declared RngStream. */
-
- for (int i = 0; i < 6; ++i) {
- Bg[i] = Cg[i] = Ig[i] = nextSeed[i];
- }
-
- MatVecModM (A1p127, nextSeed, nextSeed, m1);
- MatVecModM (A2p127, &nextSeed[3], &nextSeed[3], m2);
-}
-
-//-------------------------------------------------------------------------
-// Reset Stream to beginning of Stream.
-//
-void RngStream::ResetStartStream ()
-{
- for (int i = 0; i < 6; ++i)
- Cg[i] = Bg[i] = Ig[i];
-}
-
-
-//-------------------------------------------------------------------------
-// Reset Stream to beginning of SubStream.
-//
-void RngStream::ResetStartSubstream ()
-{
- for (int i = 0; i < 6; ++i)
- Cg[i] = Bg[i];
-}
-
-
-//-------------------------------------------------------------------------
-// Reset Stream to NextSubStream.
-//
-void RngStream::ResetNextSubstream ()
+void
+RngStream::AdvanceNthBy (uint64_t nth, int by, double state[6])
{
- MatVecModM (A1p76, Bg, Bg, m1);
- MatVecModM (A2p76, &Bg[3], &Bg[3], m2);
- for (int i = 0; i < 6; ++i)
- Cg[i] = Bg[i];
-}
-
-//-------------------------------------------------------------------------
-// Reset Stream to Nth SubStream.
-//
-void RngStream::ResetNthSubstream (uint32_t N)
-{
- if(N==0) return;
- for(uint32_t i=0; i<N; ++i) {
- MatVecModM (A1p76, Bg, Bg, m1);
- MatVecModM (A2p76, &Bg[3], &Bg[3], m2);
- }
- for (int i = 0; i < 6; ++i)
- Cg[i] = Bg[i];
-}
-
-//-------------------------------------------------------------------------
-bool RngStream::SetPackageSeed (const uint32_t seed[6])
-{
- if (!CheckSeed (seed))
+ Matrix matrix1,matrix2;
+ for (int i = 0; i < 64; i++)
{
- return false;
- }
- for (int i = 0; i < 6; ++i)
- nextSeed[i] = seed[i];
- return true;
-}
-bool
-RngStream::SetPackageSeed (uint32_t seed)
-{
- uint32_t seeds[6] = { seed, seed, seed, seed, seed, seed};
- return SetPackageSeed (seeds);
-}
-void
-RngStream::GetPackageSeed (uint32_t seed[6])
-{
- IntegerValue value;
- g_rngSeed.GetValue (value);
- uint32_t theSeed = value.Get ();
- for (int i = 0; i < 6; i++)
- {
- seed[i] = static_cast<uint32_t> (theSeed);
+ int nbit = 63 - i;
+ int bit = (nth >> nbit) & 0x1;
+ if (bit)
+ {
+ PowerOfTwoMatrix(by + nbit, matrix1, matrix2);
+ MatVecModM (matrix1, state, state, m1);
+ MatVecModM (matrix2, &state[3], &state[3], m2);
+ }
}
}
-void
-RngStream::SetPackageRun (uint32_t run)
-{
- g_rngRun.SetValue (IntegerValue (run));
-}
-uint32_t
-RngStream::GetPackageRun (void)
-{
- IntegerValue run;
- g_rngRun.GetValue (run);
- return run.Get ();
-}
-bool
-RngStream::CheckSeed (uint32_t seed)
-{
- uint32_t seeds[6] = { seed, seed, seed, seed, seed, seed};
- return CheckSeed (seeds);
-}
-
-
-
-//-------------------------------------------------------------------------
-bool RngStream::SetSeeds (const uint32_t seed[6])
-{
- if (!CheckSeed (seed)) return false;
- for (int i = 0; i < 6; ++i)
- Cg[i] = Bg[i] = Ig[i] = seed[i];
- return true;
-}
-
-
-//-------------------------------------------------------------------------
-// if e > 0, let n = 2^e + c;
-// if e < 0, let n = -2^(-e) + c;
-// if e = 0, let n = c.
-// Jump n steps forward if n > 0, backwards if n < 0.
-//
-void RngStream::AdvanceState (int32_t e, int32_t c)
-{
- double B1[3][3], C1[3][3], B2[3][3], C2[3][3];
-
- if (e > 0) {
- MatTwoPowModM (A1p0, B1, m1, e);
- MatTwoPowModM (A2p0, B2, m2, e);
- } else if (e < 0) {
- MatTwoPowModM (InvA1, B1, m1, -e);
- MatTwoPowModM (InvA2, B2, m2, -e);
- }
-
- if (c >= 0) {
- MatPowModM (A1p0, C1, m1, c);
- MatPowModM (A2p0, C2, m2, c);
- } else {
- MatPowModM (InvA1, C1, m1, -c);
- MatPowModM (InvA2, C2, m2, -c);
- }
-
- if (e) {
- MatMatModM (B1, C1, C1, m1);
- MatMatModM (B2, C2, C2, m2);
- }
-
- MatVecModM (C1, Cg, Cg, m1);
- MatVecModM (C2, &Cg[3], &Cg[3], m2);
-}
-
-
-//-------------------------------------------------------------------------
-void RngStream::GetState (uint32_t seed[6]) const
-{
- for (int i = 0; i < 6; ++i)
- seed[i] = static_cast<uint32_t> (Cg[i]);
-}
-
-
-//-------------------------------------------------------------------------
-void RngStream::IncreasedPrecis (bool incp)
-{
- incPrec = incp;
-}
-
-
-//-------------------------------------------------------------------------
-void RngStream::SetAntithetic (bool a)
-{
- anti = a;
-}
-
-
-//-------------------------------------------------------------------------
-// Generate the next random number.
-//
-double RngStream::RandU01 ()
-{
- if (incPrec)
- return U01d ();
- else
- return U01 ();
-}
-
-
-//-------------------------------------------------------------------------
-// Generate the next random integer.
-//
-int32_t RngStream::RandInt (int32_t low, int32_t high)
-{
- return low + static_cast<int32_t> ((high - low + 1) * RandU01 ());
-};
} // namespace ns3
--- a/src/core/model/rng-stream.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/core/model/rng-stream.h Tue Jul 31 19:18:23 2012 +0200
@@ -36,38 +36,21 @@
* class are explained in:
* http://www.iro.umontreal.ca/~lecuyer/myftp/papers/streams00.pdf
*/
-class RngStream {
-public: //public api
- RngStream ();
+class RngStream
+{
+public:
+ RngStream (uint32_t seed, uint64_t stream, uint64_t substream);
RngStream (const RngStream&);
- void InitializeStream (); // Separate initialization
- void ResetStartStream ();
- void ResetStartSubstream ();
- void ResetNextSubstream ();
- void ResetNthSubstream (uint32_t N);
- void SetAntithetic (bool a);
- void IncreasedPrecis (bool incp);
- bool SetSeeds (const uint32_t seed[6]);
- void AdvanceState (int32_t e, int32_t c);
- void GetState (uint32_t seed[6]) const;
- double RandU01 ();
- int32_t RandInt (int32_t i, int32_t j);
-public: //public static api
- static bool SetPackageSeed (uint32_t seed);
- static bool SetPackageSeed (const uint32_t seed[6]);
- static void GetPackageSeed (uint32_t seed[6]);
- static void SetPackageRun (uint32_t run);
- static uint32_t GetPackageRun (void);
- static bool CheckSeed (const uint32_t seed[6]);
- static bool CheckSeed (uint32_t seed);
-private: //members
- double Cg[6], Bg[6], Ig[6];
- bool anti, incPrec;
- double U01 ();
- double U01d ();
- static uint32_t EnsureGlobalInitialized (void);
-private: //static data
- static double nextSeed[6];
+ /**
+ * Generate the next random number for this stream.
+ * Uniformly distributed between 0 and 1.
+ */
+ double RandU01 (void);
+
+private:
+ void AdvanceNthBy (uint64_t nth, int by, double state[6]);
+
+ double m_currentState[6];
};
} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/test/random-variable-stream-test-suite.cc Tue Jul 31 19:18:23 2012 +0200
@@ -0,0 +1,2826 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009-12 University of Washington
+ *
+ * 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
+ *
+ * This file is based on rng-test-suite.cc.
+ *
+ * Modified by Mitch Watrous <watrous@u.washington.edu>
+ *
+ */
+
+
+#include <math.h>
+#include <gsl/gsl_cdf.h>
+#include <gsl/gsl_histogram.h>
+#include <gsl/gsl_sf_zeta.h>
+#include <time.h>
+#include <fstream>
+#include <cmath>
+
+#include "ns3/boolean.h"
+#include "ns3/double.h"
+#include "ns3/string.h"
+#include "ns3/integer.h"
+#include "ns3/test.h"
+#include "ns3/rng-seed-manager.h"
+#include "ns3/random-variable-stream.h"
+
+using namespace ns3;
+
+namespace {
+
+void
+FillHistoRangeUniformly (double *array, uint32_t n, double start, double end)
+{
+ double increment = (end - start) / (n - 1.);
+ double d = start;
+
+ for (uint32_t i = 0; i < n; ++i)
+ {
+ array[i] = d;
+ d += increment;
+ }
+}
+
+} // anonymous namespace
+
+// ===========================================================================
+// Test case for uniform distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamUniformTestCase : public TestCase
+{
+public:
+ static const uint32_t N_RUNS = 5;
+ static const uint32_t N_BINS = 50;
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamUniformTestCase ();
+ virtual ~RandomVariableStreamUniformTestCase ();
+
+ double ChiSquaredTest (Ptr<UniformRandomVariable> u);
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamUniformTestCase::RandomVariableStreamUniformTestCase ()
+ : TestCase ("Uniform Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamUniformTestCase::~RandomVariableStreamUniformTestCase ()
+{
+}
+
+double
+RandomVariableStreamUniformTestCase::ChiSquaredTest (Ptr<UniformRandomVariable> u)
+{
+ gsl_histogram * h = gsl_histogram_alloc (N_BINS);
+
+ // Note that this assumes that the range for u is [0,1], which is
+ // the default range for this distribution.
+ gsl_histogram_set_ranges_uniform (h, 0., 1.);
+
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ gsl_histogram_increment (h, u->GetValue ());
+ }
+
+ double tmp[N_BINS];
+
+ double expected = ((double)N_MEASUREMENTS / (double)N_BINS);
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ tmp[i] = gsl_histogram_get (h, i);
+ tmp[i] -= expected;
+ tmp[i] *= tmp[i];
+ tmp[i] /= expected;
+ }
+
+ gsl_histogram_free (h);
+
+ double chiSquared = 0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ chiSquared += tmp[i];
+ }
+
+ return chiSquared;
+}
+
+void
+RandomVariableStreamUniformTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double sum = 0.;
+ double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
+
+ for (uint32_t i = 0; i < N_RUNS; ++i)
+ {
+ Ptr<UniformRandomVariable> u = CreateObject<UniformRandomVariable> ();
+ double result = ChiSquaredTest (u);
+ sum += result;
+ }
+
+ sum /= (double)N_RUNS;
+
+ NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
+
+ double min = 0.0;
+ double max = 10.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable> ();
+
+ x->SetAttribute ("Min", DoubleValue (min));
+ x->SetAttribute ("Max", DoubleValue (max));
+
+ // Test that values are always within the range:
+ //
+ // [min, max)
+ //
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ ((value >= min), true, "Value less than minimum.");
+ NS_TEST_ASSERT_MSG_LT (value, max, "Value greater than or equal to maximum.");
+ }
+
+
+}
+
+// ===========================================================================
+// Test case for antithetic uniform distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamUniformAntitheticTestCase : public TestCase
+{
+public:
+ static const uint32_t N_RUNS = 5;
+ static const uint32_t N_BINS = 50;
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamUniformAntitheticTestCase ();
+ virtual ~RandomVariableStreamUniformAntitheticTestCase ();
+
+ double ChiSquaredTest (Ptr<UniformRandomVariable> u);
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamUniformAntitheticTestCase::RandomVariableStreamUniformAntitheticTestCase ()
+ : TestCase ("Antithetic Uniform Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamUniformAntitheticTestCase::~RandomVariableStreamUniformAntitheticTestCase ()
+{
+}
+
+double
+RandomVariableStreamUniformAntitheticTestCase::ChiSquaredTest (Ptr<UniformRandomVariable> u)
+{
+ gsl_histogram * h = gsl_histogram_alloc (N_BINS);
+
+ // Note that this assumes that the range for u is [0,1], which is
+ // the default range for this distribution.
+ gsl_histogram_set_ranges_uniform (h, 0., 1.);
+
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ gsl_histogram_increment (h, u->GetValue ());
+ }
+
+ double tmp[N_BINS];
+
+ double expected = ((double)N_MEASUREMENTS / (double)N_BINS);
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ tmp[i] = gsl_histogram_get (h, i);
+ tmp[i] -= expected;
+ tmp[i] *= tmp[i];
+ tmp[i] /= expected;
+ }
+
+ gsl_histogram_free (h);
+
+ double chiSquared = 0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ chiSquared += tmp[i];
+ }
+
+ return chiSquared;
+}
+
+void
+RandomVariableStreamUniformAntitheticTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double sum = 0.;
+ double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
+
+ for (uint32_t i = 0; i < N_RUNS; ++i)
+ {
+ Ptr<UniformRandomVariable> u = CreateObject<UniformRandomVariable> ();
+
+ // Make this generate antithetic values.
+ u->SetAttribute ("Antithetic", BooleanValue (true));
+
+ double result = ChiSquaredTest (u);
+ sum += result;
+ }
+
+ sum /= (double)N_RUNS;
+
+ NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
+
+ double min = 0.0;
+ double max = 10.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable> ();
+
+ // Make this generate antithetic values.
+ x->SetAttribute ("Antithetic", BooleanValue (true));
+
+ x->SetAttribute ("Min", DoubleValue (min));
+ x->SetAttribute ("Max", DoubleValue (max));
+
+ // Test that values are always within the range:
+ //
+ // [min, max)
+ //
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ ((value >= min), true, "Value less than minimum.");
+ NS_TEST_ASSERT_MSG_LT (value, max, "Value greater than or equal to maximum.");
+ }
+
+
+}
+
+// ===========================================================================
+// Test case for constant random variable stream generator
+// ===========================================================================
+class RandomVariableStreamConstantTestCase : public TestCase
+{
+public:
+ static const uint32_t N_MEASUREMENTS = 1000000;
+ static const double TOLERANCE = 1e-8;
+
+ RandomVariableStreamConstantTestCase ();
+ virtual ~RandomVariableStreamConstantTestCase ();
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamConstantTestCase::RandomVariableStreamConstantTestCase ()
+ : TestCase ("Constant Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamConstantTestCase::~RandomVariableStreamConstantTestCase ()
+{
+}
+
+void
+RandomVariableStreamConstantTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ Ptr<ConstantRandomVariable> c = CreateObject<ConstantRandomVariable> ();
+
+ double constant;
+
+ // Test that the constant value can be changed using its attribute.
+ constant = 10.0;
+ c->SetAttribute ("Constant", DoubleValue (constant));
+ NS_TEST_ASSERT_MSG_EQ_TOL (c->GetValue (), constant, TOLERANCE, "Constant value changed");
+ c->SetAttribute ("Constant", DoubleValue (20.0));
+ NS_TEST_ASSERT_MSG_NE (c->GetValue (), constant, "Constant value not changed");
+
+ // Test that the constant value does not change.
+ constant = c->GetValue ();
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ NS_TEST_ASSERT_MSG_EQ_TOL (c->GetValue (), constant, TOLERANCE, "Constant value changed in loop");
+ }
+}
+
+// ===========================================================================
+// Test case for sequential random variable stream generator
+// ===========================================================================
+class RandomVariableStreamSequentialTestCase : public TestCase
+{
+public:
+ static const double TOLERANCE = 1e-8;
+
+ RandomVariableStreamSequentialTestCase ();
+ virtual ~RandomVariableStreamSequentialTestCase ();
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamSequentialTestCase::RandomVariableStreamSequentialTestCase ()
+ : TestCase ("Sequential Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamSequentialTestCase::~RandomVariableStreamSequentialTestCase ()
+{
+}
+
+void
+RandomVariableStreamSequentialTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ Ptr<SequentialRandomVariable> s = CreateObject<SequentialRandomVariable> ();
+
+ // The following four attributes should give the sequence
+ //
+ // 4, 4, 7, 7, 10, 10
+ //
+ s->SetAttribute ("Min", DoubleValue (4));
+ s->SetAttribute ("Max", DoubleValue (11));
+ s->SetAttribute ("Increment", StringValue("ns3::UniformRandomVariable[Min=3.0|Max=3.0]"));
+ s->SetAttribute ("Consecutive", IntegerValue (2));
+
+ double value;
+
+ // Test that the sequencet is correct.
+ value = s->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ_TOL (value, 4, TOLERANCE, "Sequence value 1 wrong.");
+ value = s->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ_TOL (value, 4, TOLERANCE, "Sequence value 2 wrong.");
+ value = s->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ_TOL (value, 7, TOLERANCE, "Sequence value 3 wrong.");
+ value = s->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ_TOL (value, 7, TOLERANCE, "Sequence value 4 wrong.");
+ value = s->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ_TOL (value, 10, TOLERANCE, "Sequence value 5 wrong.");
+ value = s->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ_TOL (value, 10, TOLERANCE, "Sequence value 6 wrong.");
+
+}
+
+// ===========================================================================
+// Test case for normal distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamNormalTestCase : public TestCase
+{
+public:
+ static const uint32_t N_RUNS = 5;
+ static const uint32_t N_BINS = 50;
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamNormalTestCase ();
+ virtual ~RandomVariableStreamNormalTestCase ();
+
+ double ChiSquaredTest (Ptr<NormalRandomVariable> n);
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamNormalTestCase::RandomVariableStreamNormalTestCase ()
+ : TestCase ("Normal Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamNormalTestCase::~RandomVariableStreamNormalTestCase ()
+{
+}
+
+double
+RandomVariableStreamNormalTestCase::ChiSquaredTest (Ptr<NormalRandomVariable> n)
+{
+ gsl_histogram * h = gsl_histogram_alloc (N_BINS);
+
+ double range[N_BINS + 1];
+ FillHistoRangeUniformly (range, N_BINS + 1, -4., 4.);
+ range[0] = -std::numeric_limits<double>::max ();
+ range[N_BINS] = std::numeric_limits<double>::max ();
+
+ gsl_histogram_set_ranges (h, range, N_BINS + 1);
+
+ double expected[N_BINS];
+
+ // Note that this assumes that n has mean equal to zero and standard
+ // deviation equal to one, which are their default values for this
+ // distribution.
+ double sigma = 1.;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ expected[i] = gsl_cdf_gaussian_P (range[i + 1], sigma) - gsl_cdf_gaussian_P (range[i], sigma);
+ expected[i] *= N_MEASUREMENTS;
+ }
+
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ gsl_histogram_increment (h, n->GetValue ());
+ }
+
+ double tmp[N_BINS];
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ tmp[i] = gsl_histogram_get (h, i);
+ tmp[i] -= expected[i];
+ tmp[i] *= tmp[i];
+ tmp[i] /= expected[i];
+ }
+
+ gsl_histogram_free (h);
+
+ double chiSquared = 0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ chiSquared += tmp[i];
+ }
+
+ return chiSquared;
+}
+
+void
+RandomVariableStreamNormalTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double sum = 0.;
+ double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
+
+ for (uint32_t i = 0; i < N_RUNS; ++i)
+ {
+ Ptr<NormalRandomVariable> n = CreateObject<NormalRandomVariable> ();
+ double result = ChiSquaredTest (n);
+ sum += result;
+ }
+
+ sum /= (double)N_RUNS;
+
+ NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
+
+ double mean = 5.0;
+ double variance = 2.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<NormalRandomVariable> x = CreateObject<NormalRandomVariable> ();
+ x->SetAttribute ("Mean", DoubleValue (mean));
+ x->SetAttribute ("Variance", DoubleValue (variance));
+
+ // Calculate the mean of these values.
+ sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean of the values returned by a
+ // normally distributed random variable is equal to mean.
+ double expectedMean = mean;
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = expectedMean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for antithetic normal distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamNormalAntitheticTestCase : public TestCase
+{
+public:
+ static const uint32_t N_RUNS = 5;
+ static const uint32_t N_BINS = 50;
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamNormalAntitheticTestCase ();
+ virtual ~RandomVariableStreamNormalAntitheticTestCase ();
+
+ double ChiSquaredTest (Ptr<NormalRandomVariable> n);
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamNormalAntitheticTestCase::RandomVariableStreamNormalAntitheticTestCase ()
+ : TestCase ("Antithetic Normal Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamNormalAntitheticTestCase::~RandomVariableStreamNormalAntitheticTestCase ()
+{
+}
+
+double
+RandomVariableStreamNormalAntitheticTestCase::ChiSquaredTest (Ptr<NormalRandomVariable> n)
+{
+ gsl_histogram * h = gsl_histogram_alloc (N_BINS);
+
+ double range[N_BINS + 1];
+ FillHistoRangeUniformly (range, N_BINS + 1, -4., 4.);
+ range[0] = -std::numeric_limits<double>::max ();
+ range[N_BINS] = std::numeric_limits<double>::max ();
+
+ gsl_histogram_set_ranges (h, range, N_BINS + 1);
+
+ double expected[N_BINS];
+
+ // Note that this assumes that n has mean equal to zero and standard
+ // deviation equal to one, which are their default values for this
+ // distribution.
+ double sigma = 1.;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ expected[i] = gsl_cdf_gaussian_P (range[i + 1], sigma) - gsl_cdf_gaussian_P (range[i], sigma);
+ expected[i] *= N_MEASUREMENTS;
+ }
+
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ gsl_histogram_increment (h, n->GetValue ());
+ }
+
+ double tmp[N_BINS];
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ tmp[i] = gsl_histogram_get (h, i);
+ tmp[i] -= expected[i];
+ tmp[i] *= tmp[i];
+ tmp[i] /= expected[i];
+ }
+
+ gsl_histogram_free (h);
+
+ double chiSquared = 0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ chiSquared += tmp[i];
+ }
+
+ return chiSquared;
+}
+
+void
+RandomVariableStreamNormalAntitheticTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double sum = 0.;
+ double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
+
+ for (uint32_t i = 0; i < N_RUNS; ++i)
+ {
+ Ptr<NormalRandomVariable> n = CreateObject<NormalRandomVariable> ();
+
+ // Make this generate antithetic values.
+ n->SetAttribute ("Antithetic", BooleanValue (true));
+
+ double result = ChiSquaredTest (n);
+ sum += result;
+ }
+
+ sum /= (double)N_RUNS;
+
+ NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
+
+ double mean = 5.0;
+ double variance = 2.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<NormalRandomVariable> x = CreateObject<NormalRandomVariable> ();
+ x->SetAttribute ("Mean", DoubleValue (mean));
+ x->SetAttribute ("Variance", DoubleValue (variance));
+
+ // Make this generate antithetic values.
+ x->SetAttribute ("Antithetic", BooleanValue (true));
+
+ // Calculate the mean of these values.
+ sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean of the values returned by a
+ // normally distributed random variable is equal to mean.
+ double expectedMean = mean;
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = expectedMean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for exponential distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamExponentialTestCase : public TestCase
+{
+public:
+ static const uint32_t N_RUNS = 5;
+ static const uint32_t N_BINS = 50;
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamExponentialTestCase ();
+ virtual ~RandomVariableStreamExponentialTestCase ();
+
+ double ChiSquaredTest (Ptr<ExponentialRandomVariable> e);
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamExponentialTestCase::RandomVariableStreamExponentialTestCase ()
+ : TestCase ("Exponential Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamExponentialTestCase::~RandomVariableStreamExponentialTestCase ()
+{
+}
+
+double
+RandomVariableStreamExponentialTestCase::ChiSquaredTest (Ptr<ExponentialRandomVariable> e)
+{
+ gsl_histogram * h = gsl_histogram_alloc (N_BINS);
+
+ double range[N_BINS + 1];
+ FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
+ range[N_BINS] = std::numeric_limits<double>::max ();
+
+ gsl_histogram_set_ranges (h, range, N_BINS + 1);
+
+ double expected[N_BINS];
+
+ // Note that this assumes that e has mean equal to one, which is the
+ // default value for this distribution.
+ double mu = 1.;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ expected[i] = gsl_cdf_exponential_P (range[i + 1], mu) - gsl_cdf_exponential_P (range[i], mu);
+ expected[i] *= N_MEASUREMENTS;
+ }
+
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ gsl_histogram_increment (h, e->GetValue ());
+ }
+
+ double tmp[N_BINS];
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ tmp[i] = gsl_histogram_get (h, i);
+ tmp[i] -= expected[i];
+ tmp[i] *= tmp[i];
+ tmp[i] /= expected[i];
+ }
+
+ gsl_histogram_free (h);
+
+ double chiSquared = 0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ chiSquared += tmp[i];
+ }
+
+ return chiSquared;
+}
+
+void
+RandomVariableStreamExponentialTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double sum = 0.;
+ double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
+
+ for (uint32_t i = 0; i < N_RUNS; ++i)
+ {
+ Ptr<ExponentialRandomVariable> e = CreateObject<ExponentialRandomVariable> ();
+ double result = ChiSquaredTest (e);
+ sum += result;
+ }
+
+ sum /= (double)N_RUNS;
+
+ NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
+
+ double mean = 3.14;
+ double bound = 0.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<ExponentialRandomVariable> x = CreateObject<ExponentialRandomVariable> ();
+ x->SetAttribute ("Mean", DoubleValue (mean));
+ x->SetAttribute ("Bound", DoubleValue (bound));
+
+ // Calculate the mean of these values.
+ sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = mean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, mean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for antithetic exponential distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamExponentialAntitheticTestCase : public TestCase
+{
+public:
+ static const uint32_t N_RUNS = 5;
+ static const uint32_t N_BINS = 50;
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamExponentialAntitheticTestCase ();
+ virtual ~RandomVariableStreamExponentialAntitheticTestCase ();
+
+ double ChiSquaredTest (Ptr<ExponentialRandomVariable> e);
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamExponentialAntitheticTestCase::RandomVariableStreamExponentialAntitheticTestCase ()
+ : TestCase ("Antithetic Exponential Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamExponentialAntitheticTestCase::~RandomVariableStreamExponentialAntitheticTestCase ()
+{
+}
+
+double
+RandomVariableStreamExponentialAntitheticTestCase::ChiSquaredTest (Ptr<ExponentialRandomVariable> e)
+{
+ gsl_histogram * h = gsl_histogram_alloc (N_BINS);
+
+ double range[N_BINS + 1];
+ FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
+ range[N_BINS] = std::numeric_limits<double>::max ();
+
+ gsl_histogram_set_ranges (h, range, N_BINS + 1);
+
+ double expected[N_BINS];
+
+ // Note that this assumes that e has mean equal to one, which is the
+ // default value for this distribution.
+ double mu = 1.;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ expected[i] = gsl_cdf_exponential_P (range[i + 1], mu) - gsl_cdf_exponential_P (range[i], mu);
+ expected[i] *= N_MEASUREMENTS;
+ }
+
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ gsl_histogram_increment (h, e->GetValue ());
+ }
+
+ double tmp[N_BINS];
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ tmp[i] = gsl_histogram_get (h, i);
+ tmp[i] -= expected[i];
+ tmp[i] *= tmp[i];
+ tmp[i] /= expected[i];
+ }
+
+ gsl_histogram_free (h);
+
+ double chiSquared = 0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ chiSquared += tmp[i];
+ }
+
+ return chiSquared;
+}
+
+void
+RandomVariableStreamExponentialAntitheticTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double sum = 0.;
+ double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
+
+ for (uint32_t i = 0; i < N_RUNS; ++i)
+ {
+ Ptr<ExponentialRandomVariable> e = CreateObject<ExponentialRandomVariable> ();
+
+ // Make this generate antithetic values.
+ e->SetAttribute ("Antithetic", BooleanValue (true));
+
+ double result = ChiSquaredTest (e);
+ sum += result;
+ }
+
+ sum /= (double)N_RUNS;
+
+ NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
+
+ double mean = 3.14;
+ double bound = 0.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<ExponentialRandomVariable> x = CreateObject<ExponentialRandomVariable> ();
+ x->SetAttribute ("Mean", DoubleValue (mean));
+ x->SetAttribute ("Bound", DoubleValue (bound));
+
+ // Make this generate antithetic values.
+ x->SetAttribute ("Antithetic", BooleanValue (true));
+
+ // Calculate the mean of these values.
+ sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = mean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, mean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for Pareto distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamParetoTestCase : public TestCase
+{
+public:
+ static const uint32_t N_RUNS = 5;
+ static const uint32_t N_BINS = 50;
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamParetoTestCase ();
+ virtual ~RandomVariableStreamParetoTestCase ();
+
+ double ChiSquaredTest (Ptr<ParetoRandomVariable> p);
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamParetoTestCase::RandomVariableStreamParetoTestCase ()
+ : TestCase ("Pareto Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamParetoTestCase::~RandomVariableStreamParetoTestCase ()
+{
+}
+
+double
+RandomVariableStreamParetoTestCase::ChiSquaredTest (Ptr<ParetoRandomVariable> p)
+{
+ gsl_histogram * h = gsl_histogram_alloc (N_BINS);
+
+ double range[N_BINS + 1];
+ FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
+ range[N_BINS] = std::numeric_limits<double>::max ();
+
+ gsl_histogram_set_ranges (h, range, N_BINS + 1);
+
+ double expected[N_BINS];
+
+ // Note that this assumes that p has mean equal to 1 and shape equal
+ // to 2, which are their default values for this distribution.
+ double mean = 1.0;
+ double shape = 2.0;
+ double scale = mean * (shape - 1.0) / shape;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ expected[i] = gsl_cdf_pareto_P (range[i + 1], shape, scale) - gsl_cdf_pareto_P (range[i], shape, scale);
+ expected[i] *= N_MEASUREMENTS;
+ }
+
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ gsl_histogram_increment (h, p->GetValue ());
+ }
+
+ double tmp[N_BINS];
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ tmp[i] = gsl_histogram_get (h, i);
+ tmp[i] -= expected[i];
+ tmp[i] *= tmp[i];
+ tmp[i] /= expected[i];
+ }
+
+ gsl_histogram_free (h);
+
+ double chiSquared = 0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ chiSquared += tmp[i];
+ }
+
+ return chiSquared;
+}
+
+void
+RandomVariableStreamParetoTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double sum = 0.;
+ double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
+
+ for (uint32_t i = 0; i < N_RUNS; ++i)
+ {
+ Ptr<ParetoRandomVariable> e = CreateObject<ParetoRandomVariable> ();
+ double result = ChiSquaredTest (e);
+ sum += result;
+ }
+
+ sum /= (double)N_RUNS;
+
+ NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
+
+ double mean = 5.0;
+ double shape = 2.0;
+ double scale = mean * (shape - 1.0) / shape;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<ParetoRandomVariable> x = CreateObject<ParetoRandomVariable> ();
+ x->SetAttribute ("Mean", DoubleValue (mean));
+ x->SetAttribute ("Shape", DoubleValue (shape));
+
+ // Calculate the mean of these values.
+ sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean is given by
+ //
+ // shape * scale
+ // E[value] = --------------- ,
+ // shape - 1
+ //
+ // where
+ //
+ // scale = mean * (shape - 1.0) / shape .
+ double expectedMean = (shape * scale) / (shape - 1.0);
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = expectedMean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for antithetic Pareto distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamParetoAntitheticTestCase : public TestCase
+{
+public:
+ static const uint32_t N_RUNS = 5;
+ static const uint32_t N_BINS = 50;
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamParetoAntitheticTestCase ();
+ virtual ~RandomVariableStreamParetoAntitheticTestCase ();
+
+ double ChiSquaredTest (Ptr<ParetoRandomVariable> p);
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamParetoAntitheticTestCase::RandomVariableStreamParetoAntitheticTestCase ()
+ : TestCase ("Antithetic Pareto Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamParetoAntitheticTestCase::~RandomVariableStreamParetoAntitheticTestCase ()
+{
+}
+
+double
+RandomVariableStreamParetoAntitheticTestCase::ChiSquaredTest (Ptr<ParetoRandomVariable> p)
+{
+ gsl_histogram * h = gsl_histogram_alloc (N_BINS);
+
+ double range[N_BINS + 1];
+ FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
+ range[N_BINS] = std::numeric_limits<double>::max ();
+
+ gsl_histogram_set_ranges (h, range, N_BINS + 1);
+
+ double expected[N_BINS];
+
+ // Note that this assumes that p has mean equal to 1 and shape equal
+ // to 2, which are their default values for this distribution.
+ double mean = 1.0;
+ double shape = 2.0;
+ double scale = mean * (shape - 1.0) / shape;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ expected[i] = gsl_cdf_pareto_P (range[i + 1], shape, scale) - gsl_cdf_pareto_P (range[i], shape, scale);
+ expected[i] *= N_MEASUREMENTS;
+ }
+
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ gsl_histogram_increment (h, p->GetValue ());
+ }
+
+ double tmp[N_BINS];
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ tmp[i] = gsl_histogram_get (h, i);
+ tmp[i] -= expected[i];
+ tmp[i] *= tmp[i];
+ tmp[i] /= expected[i];
+ }
+
+ gsl_histogram_free (h);
+
+ double chiSquared = 0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ chiSquared += tmp[i];
+ }
+
+ return chiSquared;
+}
+
+void
+RandomVariableStreamParetoAntitheticTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double sum = 0.;
+ double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
+
+ for (uint32_t i = 0; i < N_RUNS; ++i)
+ {
+ Ptr<ParetoRandomVariable> e = CreateObject<ParetoRandomVariable> ();
+
+ // Make this generate antithetic values.
+ e->SetAttribute ("Antithetic", BooleanValue (true));
+
+ double result = ChiSquaredTest (e);
+ sum += result;
+ }
+
+ sum /= (double)N_RUNS;
+
+ NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
+
+ double mean = 5.0;
+ double shape = 2.0;
+ double scale = mean * (shape - 1.0) / shape;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<ParetoRandomVariable> x = CreateObject<ParetoRandomVariable> ();
+ x->SetAttribute ("Mean", DoubleValue (mean));
+ x->SetAttribute ("Shape", DoubleValue (shape));
+
+ // Make this generate antithetic values.
+ x->SetAttribute ("Antithetic", BooleanValue (true));
+
+ // Calculate the mean of these values.
+ sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean is given by
+ //
+ // shape * scale
+ // E[value] = --------------- ,
+ // shape - 1
+ //
+ // where
+ //
+ // scale = mean * (shape - 1.0) / shape .
+ //
+ double expectedMean = (shape * scale) / (shape - 1.0);
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = expectedMean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for Weibull distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamWeibullTestCase : public TestCase
+{
+public:
+ static const uint32_t N_RUNS = 5;
+ static const uint32_t N_BINS = 50;
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamWeibullTestCase ();
+ virtual ~RandomVariableStreamWeibullTestCase ();
+
+ double ChiSquaredTest (Ptr<WeibullRandomVariable> p);
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamWeibullTestCase::RandomVariableStreamWeibullTestCase ()
+ : TestCase ("Weibull Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamWeibullTestCase::~RandomVariableStreamWeibullTestCase ()
+{
+}
+
+double
+RandomVariableStreamWeibullTestCase::ChiSquaredTest (Ptr<WeibullRandomVariable> p)
+{
+ gsl_histogram * h = gsl_histogram_alloc (N_BINS);
+
+ double range[N_BINS + 1];
+ FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
+ range[N_BINS] = std::numeric_limits<double>::max ();
+
+ gsl_histogram_set_ranges (h, range, N_BINS + 1);
+
+ double expected[N_BINS];
+
+ // Note that this assumes that p has shape equal to one and scale
+ // equal to one, which are their default values for this
+ // distribution.
+ double a = 1.0;
+ double b = 1.0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ expected[i] = gsl_cdf_weibull_P (range[i + 1], a, b) - gsl_cdf_weibull_P (range[i], a, b);
+ expected[i] *= N_MEASUREMENTS;
+ }
+
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ gsl_histogram_increment (h, p->GetValue ());
+ }
+
+ double tmp[N_BINS];
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ tmp[i] = gsl_histogram_get (h, i);
+ tmp[i] -= expected[i];
+ tmp[i] *= tmp[i];
+ tmp[i] /= expected[i];
+ }
+
+ gsl_histogram_free (h);
+
+ double chiSquared = 0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ chiSquared += tmp[i];
+ }
+
+ return chiSquared;
+}
+
+void
+RandomVariableStreamWeibullTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double sum = 0.;
+ double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
+
+ for (uint32_t i = 0; i < N_RUNS; ++i)
+ {
+ Ptr<WeibullRandomVariable> e = CreateObject<WeibullRandomVariable> ();
+ double result = ChiSquaredTest (e);
+ sum += result;
+ }
+
+ sum /= (double)N_RUNS;
+
+ NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
+
+ double scale = 5.0;
+ double shape = 1.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<WeibullRandomVariable> x = CreateObject<WeibullRandomVariable> ();
+ x->SetAttribute ("Scale", DoubleValue (scale));
+ x->SetAttribute ("Shape", DoubleValue (shape));
+
+ // Calculate the mean of these values.
+ sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean of the values returned by a
+ // Weibull distributed random variable is
+ //
+ // E[value] = scale * Gamma(1 + 1 / shape) ,
+ //
+ // where Gamma() is the Gamma function. Note that
+ //
+ // Gamma(n) = (n - 1)!
+ //
+ // if n is a positive integer.
+ //
+ // For this test,
+ //
+ // Gamma(1 + 1 / shape) = Gamma(1 + 1 / 1)
+ // = Gamma(2)
+ // = (2 - 1)!
+ // = 1
+ //
+ // which means
+ //
+ // E[value] = scale .
+ //
+ double expectedMean = scale;
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = expectedMean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for antithetic Weibull distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamWeibullAntitheticTestCase : public TestCase
+{
+public:
+ static const uint32_t N_RUNS = 5;
+ static const uint32_t N_BINS = 50;
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamWeibullAntitheticTestCase ();
+ virtual ~RandomVariableStreamWeibullAntitheticTestCase ();
+
+ double ChiSquaredTest (Ptr<WeibullRandomVariable> p);
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamWeibullAntitheticTestCase::RandomVariableStreamWeibullAntitheticTestCase ()
+ : TestCase ("Antithetic Weibull Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamWeibullAntitheticTestCase::~RandomVariableStreamWeibullAntitheticTestCase ()
+{
+}
+
+double
+RandomVariableStreamWeibullAntitheticTestCase::ChiSquaredTest (Ptr<WeibullRandomVariable> p)
+{
+ gsl_histogram * h = gsl_histogram_alloc (N_BINS);
+
+ double range[N_BINS + 1];
+ FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
+ range[N_BINS] = std::numeric_limits<double>::max ();
+
+ gsl_histogram_set_ranges (h, range, N_BINS + 1);
+
+ double expected[N_BINS];
+
+ // Note that this assumes that p has shape equal to one and scale
+ // equal to one, which are their default values for this
+ // distribution.
+ double a = 1.0;
+ double b = 1.0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ expected[i] = gsl_cdf_weibull_P (range[i + 1], a, b) - gsl_cdf_weibull_P (range[i], a, b);
+ expected[i] *= N_MEASUREMENTS;
+ }
+
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ gsl_histogram_increment (h, p->GetValue ());
+ }
+
+ double tmp[N_BINS];
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ tmp[i] = gsl_histogram_get (h, i);
+ tmp[i] -= expected[i];
+ tmp[i] *= tmp[i];
+ tmp[i] /= expected[i];
+ }
+
+ gsl_histogram_free (h);
+
+ double chiSquared = 0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ chiSquared += tmp[i];
+ }
+
+ return chiSquared;
+}
+
+void
+RandomVariableStreamWeibullAntitheticTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double sum = 0.;
+ double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
+
+ for (uint32_t i = 0; i < N_RUNS; ++i)
+ {
+ Ptr<WeibullRandomVariable> e = CreateObject<WeibullRandomVariable> ();
+
+ // Make this generate antithetic values.
+ e->SetAttribute ("Antithetic", BooleanValue (true));
+
+ double result = ChiSquaredTest (e);
+ sum += result;
+ }
+
+ sum /= (double)N_RUNS;
+
+ NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
+
+ double scale = 5.0;
+ double shape = 1.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<WeibullRandomVariable> x = CreateObject<WeibullRandomVariable> ();
+ x->SetAttribute ("Scale", DoubleValue (scale));
+ x->SetAttribute ("Shape", DoubleValue (shape));
+
+ // Make this generate antithetic values.
+ x->SetAttribute ("Antithetic", BooleanValue (true));
+
+ // Calculate the mean of these values.
+ sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean of the values returned by a
+ // Weibull distributed random variable is
+ //
+ // E[value] = scale * Gamma(1 + 1 / shape) ,
+ //
+ // where Gamma() is the Gamma function. Note that
+ //
+ // Gamma(n) = (n - 1)!
+ //
+ // if n is a positive integer.
+ //
+ // For this test,
+ //
+ // Gamma(1 + 1 / shape) = Gamma(1 + 1 / 1)
+ // = Gamma(2)
+ // = (2 - 1)!
+ // = 1
+ //
+ // which means
+ //
+ // E[value] = scale .
+ //
+ double expectedMean = scale;
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = expectedMean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for log-normal distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamLogNormalTestCase : public TestCase
+{
+public:
+ static const uint32_t N_RUNS = 5;
+ static const uint32_t N_BINS = 50;
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamLogNormalTestCase ();
+ virtual ~RandomVariableStreamLogNormalTestCase ();
+
+ double ChiSquaredTest (Ptr<LogNormalRandomVariable> n);
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamLogNormalTestCase::RandomVariableStreamLogNormalTestCase ()
+ : TestCase ("Log-Normal Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamLogNormalTestCase::~RandomVariableStreamLogNormalTestCase ()
+{
+}
+
+double
+RandomVariableStreamLogNormalTestCase::ChiSquaredTest (Ptr<LogNormalRandomVariable> n)
+{
+ gsl_histogram * h = gsl_histogram_alloc (N_BINS);
+
+ double range[N_BINS + 1];
+ FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
+ range[N_BINS] = std::numeric_limits<double>::max ();
+
+ gsl_histogram_set_ranges (h, range, N_BINS + 1);
+
+ double expected[N_BINS];
+
+ // Note that this assumes that n has mu equal to zero and sigma
+ // equal to one, which are their default values for this
+ // distribution.
+ double mu = 0.0;
+ double sigma = 1.0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ expected[i] = gsl_cdf_lognormal_P (range[i + 1], mu, sigma) - gsl_cdf_lognormal_P (range[i], mu, sigma);
+ expected[i] *= N_MEASUREMENTS;
+ }
+
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ gsl_histogram_increment (h, n->GetValue ());
+ }
+
+ double tmp[N_BINS];
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ tmp[i] = gsl_histogram_get (h, i);
+ tmp[i] -= expected[i];
+ tmp[i] *= tmp[i];
+ tmp[i] /= expected[i];
+ }
+
+ gsl_histogram_free (h);
+
+ double chiSquared = 0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ chiSquared += tmp[i];
+ }
+
+ return chiSquared;
+}
+
+void
+RandomVariableStreamLogNormalTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double sum = 0.;
+ double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
+
+ for (uint32_t i = 0; i < N_RUNS; ++i)
+ {
+ Ptr<LogNormalRandomVariable> n = CreateObject<LogNormalRandomVariable> ();
+ double result = ChiSquaredTest (n);
+ sum += result;
+ }
+
+ sum /= (double)N_RUNS;
+
+ NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
+
+ double mu = 5.0;
+ double sigma = 2.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<LogNormalRandomVariable> x = CreateObject<LogNormalRandomVariable> ();
+ x->SetAttribute ("Mu", DoubleValue (mu));
+ x->SetAttribute ("Sigma", DoubleValue (sigma));
+
+ // Calculate the mean of these values.
+ sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean of the values returned by a
+ // log-normally distributed random variable is equal to
+ //
+ // 2
+ // mu + sigma / 2
+ // E[value] = e .
+ //
+ double expectedMean = std::exp(mu + sigma * sigma / 2.0);
+
+ // Test that values have approximately the right mean value.
+ //
+ // XXX This test fails sometimes if the required tolerance is less
+ // than 3%, which may be because there is a bug in the
+ // implementation or that the mean of this distribution is more
+ // senstive to its parameters than the others are.
+ double TOLERANCE = expectedMean * 3e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for antithetic log-normal distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamLogNormalAntitheticTestCase : public TestCase
+{
+public:
+ static const uint32_t N_RUNS = 5;
+ static const uint32_t N_BINS = 50;
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamLogNormalAntitheticTestCase ();
+ virtual ~RandomVariableStreamLogNormalAntitheticTestCase ();
+
+ double ChiSquaredTest (Ptr<LogNormalRandomVariable> n);
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamLogNormalAntitheticTestCase::RandomVariableStreamLogNormalAntitheticTestCase ()
+ : TestCase ("Antithetic Log-Normal Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamLogNormalAntitheticTestCase::~RandomVariableStreamLogNormalAntitheticTestCase ()
+{
+}
+
+double
+RandomVariableStreamLogNormalAntitheticTestCase::ChiSquaredTest (Ptr<LogNormalRandomVariable> n)
+{
+ gsl_histogram * h = gsl_histogram_alloc (N_BINS);
+
+ double range[N_BINS + 1];
+ FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
+ range[N_BINS] = std::numeric_limits<double>::max ();
+
+ gsl_histogram_set_ranges (h, range, N_BINS + 1);
+
+ double expected[N_BINS];
+
+ // Note that this assumes that n has mu equal to zero and sigma
+ // equal to one, which are their default values for this
+ // distribution.
+ double mu = 0.0;
+ double sigma = 1.0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ expected[i] = gsl_cdf_lognormal_P (range[i + 1], mu, sigma) - gsl_cdf_lognormal_P (range[i], mu, sigma);
+ expected[i] *= N_MEASUREMENTS;
+ }
+
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ gsl_histogram_increment (h, n->GetValue ());
+ }
+
+ double tmp[N_BINS];
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ tmp[i] = gsl_histogram_get (h, i);
+ tmp[i] -= expected[i];
+ tmp[i] *= tmp[i];
+ tmp[i] /= expected[i];
+ }
+
+ gsl_histogram_free (h);
+
+ double chiSquared = 0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ chiSquared += tmp[i];
+ }
+
+ return chiSquared;
+}
+
+void
+RandomVariableStreamLogNormalAntitheticTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double sum = 0.;
+ double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
+
+ for (uint32_t i = 0; i < N_RUNS; ++i)
+ {
+ Ptr<LogNormalRandomVariable> n = CreateObject<LogNormalRandomVariable> ();
+
+ // Make this generate antithetic values.
+ n->SetAttribute ("Antithetic", BooleanValue (true));
+
+ double result = ChiSquaredTest (n);
+ sum += result;
+ }
+
+ sum /= (double)N_RUNS;
+
+ NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
+
+ double mu = 5.0;
+ double sigma = 2.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<LogNormalRandomVariable> x = CreateObject<LogNormalRandomVariable> ();
+ x->SetAttribute ("Mu", DoubleValue (mu));
+ x->SetAttribute ("Sigma", DoubleValue (sigma));
+
+ // Make this generate antithetic values.
+ x->SetAttribute ("Antithetic", BooleanValue (true));
+
+ // Calculate the mean of these values.
+ sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean of the values returned by a
+ // log-normally distributed random variable is equal to
+ //
+ // 2
+ // mu + sigma / 2
+ // E[value] = e .
+ //
+ double expectedMean = std::exp(mu + sigma * sigma / 2.0);
+
+ // Test that values have approximately the right mean value.
+ //
+ // XXX This test fails sometimes if the required tolerance is less
+ // than 3%, which may be because there is a bug in the
+ // implementation or that the mean of this distribution is more
+ // senstive to its parameters than the others are.
+ double TOLERANCE = expectedMean * 3e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for gamma distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamGammaTestCase : public TestCase
+{
+public:
+ static const uint32_t N_RUNS = 5;
+ static const uint32_t N_BINS = 50;
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamGammaTestCase ();
+ virtual ~RandomVariableStreamGammaTestCase ();
+
+ double ChiSquaredTest (Ptr<GammaRandomVariable> n);
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamGammaTestCase::RandomVariableStreamGammaTestCase ()
+ : TestCase ("Gamma Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamGammaTestCase::~RandomVariableStreamGammaTestCase ()
+{
+}
+
+double
+RandomVariableStreamGammaTestCase::ChiSquaredTest (Ptr<GammaRandomVariable> n)
+{
+ gsl_histogram * h = gsl_histogram_alloc (N_BINS);
+
+ double range[N_BINS + 1];
+ FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
+ range[N_BINS] = std::numeric_limits<double>::max ();
+
+ gsl_histogram_set_ranges (h, range, N_BINS + 1);
+
+ double expected[N_BINS];
+
+ // Note that this assumes that n has alpha equal to one and beta
+ // equal to one, which are their default values for this
+ // distribution.
+ double alpha = 1.0;
+ double beta = 1.0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ expected[i] = gsl_cdf_gamma_P (range[i + 1], alpha, beta) - gsl_cdf_gamma_P (range[i], alpha, beta);
+ expected[i] *= N_MEASUREMENTS;
+ }
+
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ gsl_histogram_increment (h, n->GetValue ());
+ }
+
+ double tmp[N_BINS];
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ tmp[i] = gsl_histogram_get (h, i);
+ tmp[i] -= expected[i];
+ tmp[i] *= tmp[i];
+ tmp[i] /= expected[i];
+ }
+
+ gsl_histogram_free (h);
+
+ double chiSquared = 0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ chiSquared += tmp[i];
+ }
+
+ return chiSquared;
+}
+
+void
+RandomVariableStreamGammaTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double sum = 0.;
+ double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
+
+ for (uint32_t i = 0; i < N_RUNS; ++i)
+ {
+ Ptr<GammaRandomVariable> n = CreateObject<GammaRandomVariable> ();
+ double result = ChiSquaredTest (n);
+ sum += result;
+ }
+
+ sum /= (double)N_RUNS;
+
+ NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
+
+ double alpha = 5.0;
+ double beta = 2.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<GammaRandomVariable> x = CreateObject<GammaRandomVariable> ();
+ x->SetAttribute ("Alpha", DoubleValue (alpha));
+ x->SetAttribute ("Beta", DoubleValue (beta));
+
+ // Calculate the mean of these values.
+ sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean of the values returned by a
+ // gammaly distributed random variable is equal to
+ //
+ // E[value] = alpha * beta .
+ //
+ double expectedMean = alpha * beta;
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = expectedMean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for antithetic gamma distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamGammaAntitheticTestCase : public TestCase
+{
+public:
+ static const uint32_t N_RUNS = 5;
+ static const uint32_t N_BINS = 50;
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamGammaAntitheticTestCase ();
+ virtual ~RandomVariableStreamGammaAntitheticTestCase ();
+
+ double ChiSquaredTest (Ptr<GammaRandomVariable> n);
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamGammaAntitheticTestCase::RandomVariableStreamGammaAntitheticTestCase ()
+ : TestCase ("Antithetic Gamma Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamGammaAntitheticTestCase::~RandomVariableStreamGammaAntitheticTestCase ()
+{
+}
+
+double
+RandomVariableStreamGammaAntitheticTestCase::ChiSquaredTest (Ptr<GammaRandomVariable> n)
+{
+ gsl_histogram * h = gsl_histogram_alloc (N_BINS);
+
+ double range[N_BINS + 1];
+ FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
+ range[N_BINS] = std::numeric_limits<double>::max ();
+
+ gsl_histogram_set_ranges (h, range, N_BINS + 1);
+
+ double expected[N_BINS];
+
+ // Note that this assumes that n has alpha equal to one and beta
+ // equal to one, which are their default values for this
+ // distribution.
+ double alpha = 1.0;
+ double beta = 1.0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ expected[i] = gsl_cdf_gamma_P (range[i + 1], alpha, beta) - gsl_cdf_gamma_P (range[i], alpha, beta);
+ expected[i] *= N_MEASUREMENTS;
+ }
+
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ gsl_histogram_increment (h, n->GetValue ());
+ }
+
+ double tmp[N_BINS];
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ tmp[i] = gsl_histogram_get (h, i);
+ tmp[i] -= expected[i];
+ tmp[i] *= tmp[i];
+ tmp[i] /= expected[i];
+ }
+
+ gsl_histogram_free (h);
+
+ double chiSquared = 0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ chiSquared += tmp[i];
+ }
+
+ return chiSquared;
+}
+
+void
+RandomVariableStreamGammaAntitheticTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double sum = 0.;
+ double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
+
+ for (uint32_t i = 0; i < N_RUNS; ++i)
+ {
+ Ptr<GammaRandomVariable> n = CreateObject<GammaRandomVariable> ();
+
+ // Make this generate antithetic values.
+ n->SetAttribute ("Antithetic", BooleanValue (true));
+
+ double result = ChiSquaredTest (n);
+ sum += result;
+ }
+
+ sum /= (double)N_RUNS;
+
+ NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
+
+ double alpha = 5.0;
+ double beta = 2.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<GammaRandomVariable> x = CreateObject<GammaRandomVariable> ();
+
+ // Make this generate antithetic values.
+ x->SetAttribute ("Antithetic", BooleanValue (true));
+
+ x->SetAttribute ("Alpha", DoubleValue (alpha));
+ x->SetAttribute ("Beta", DoubleValue (beta));
+
+ // Calculate the mean of these values.
+ sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean of the values returned by a
+ // gammaly distributed random variable is equal to
+ //
+ // E[value] = alpha * beta .
+ //
+ double expectedMean = alpha * beta;
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = expectedMean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for Erlang distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamErlangTestCase : public TestCase
+{
+public:
+ static const uint32_t N_RUNS = 5;
+ static const uint32_t N_BINS = 50;
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamErlangTestCase ();
+ virtual ~RandomVariableStreamErlangTestCase ();
+
+ double ChiSquaredTest (Ptr<ErlangRandomVariable> n);
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamErlangTestCase::RandomVariableStreamErlangTestCase ()
+ : TestCase ("Erlang Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamErlangTestCase::~RandomVariableStreamErlangTestCase ()
+{
+}
+
+double
+RandomVariableStreamErlangTestCase::ChiSquaredTest (Ptr<ErlangRandomVariable> n)
+{
+ gsl_histogram * h = gsl_histogram_alloc (N_BINS);
+
+ double range[N_BINS + 1];
+ FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
+ range[N_BINS] = std::numeric_limits<double>::max ();
+
+ gsl_histogram_set_ranges (h, range, N_BINS + 1);
+
+ double expected[N_BINS];
+
+ // Note that this assumes that n has k equal to one and lambda
+ // equal to one, which are their default values for this
+ // distribution.
+ uint32_t k = 1;
+ double lambda = 1.0;
+
+ // Note that Erlang distribution is equal to the gamma distribution
+ // when k is an iteger, which is why the gamma distribution's cdf
+ // function can be used here.
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ expected[i] = gsl_cdf_gamma_P (range[i + 1], k, lambda) - gsl_cdf_gamma_P (range[i], k, lambda);
+ expected[i] *= N_MEASUREMENTS;
+ }
+
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ gsl_histogram_increment (h, n->GetValue ());
+ }
+
+ double tmp[N_BINS];
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ tmp[i] = gsl_histogram_get (h, i);
+ tmp[i] -= expected[i];
+ tmp[i] *= tmp[i];
+ tmp[i] /= expected[i];
+ }
+
+ gsl_histogram_free (h);
+
+ double chiSquared = 0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ chiSquared += tmp[i];
+ }
+
+ return chiSquared;
+}
+
+void
+RandomVariableStreamErlangTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double sum = 0.;
+ double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
+
+ for (uint32_t i = 0; i < N_RUNS; ++i)
+ {
+ Ptr<ErlangRandomVariable> n = CreateObject<ErlangRandomVariable> ();
+ double result = ChiSquaredTest (n);
+ sum += result;
+ }
+
+ sum /= (double)N_RUNS;
+
+ NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
+
+ uint32_t k = 5;
+ double lambda = 2.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<ErlangRandomVariable> x = CreateObject<ErlangRandomVariable> ();
+ x->SetAttribute ("K", IntegerValue (k));
+ x->SetAttribute ("Lambda", DoubleValue (lambda));
+
+ // Calculate the mean of these values.
+ sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean of the values returned by a
+ // Erlangly distributed random variable is equal to
+ //
+ // E[value] = k * lambda .
+ //
+ double expectedMean = k * lambda;
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = expectedMean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for antithetic Erlang distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamErlangAntitheticTestCase : public TestCase
+{
+public:
+ static const uint32_t N_RUNS = 5;
+ static const uint32_t N_BINS = 50;
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamErlangAntitheticTestCase ();
+ virtual ~RandomVariableStreamErlangAntitheticTestCase ();
+
+ double ChiSquaredTest (Ptr<ErlangRandomVariable> n);
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamErlangAntitheticTestCase::RandomVariableStreamErlangAntitheticTestCase ()
+ : TestCase ("Antithetic Erlang Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamErlangAntitheticTestCase::~RandomVariableStreamErlangAntitheticTestCase ()
+{
+}
+
+double
+RandomVariableStreamErlangAntitheticTestCase::ChiSquaredTest (Ptr<ErlangRandomVariable> n)
+{
+ gsl_histogram * h = gsl_histogram_alloc (N_BINS);
+
+ double range[N_BINS + 1];
+ FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
+ range[N_BINS] = std::numeric_limits<double>::max ();
+
+ gsl_histogram_set_ranges (h, range, N_BINS + 1);
+
+ double expected[N_BINS];
+
+ // Note that this assumes that n has k equal to one and lambda
+ // equal to one, which are their default values for this
+ // distribution.
+ uint32_t k = 1;
+ double lambda = 1.0;
+
+ // Note that Erlang distribution is equal to the gamma distribution
+ // when k is an iteger, which is why the gamma distribution's cdf
+ // function can be used here.
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ expected[i] = gsl_cdf_gamma_P (range[i + 1], k, lambda) - gsl_cdf_gamma_P (range[i], k, lambda);
+ expected[i] *= N_MEASUREMENTS;
+ }
+
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ gsl_histogram_increment (h, n->GetValue ());
+ }
+
+ double tmp[N_BINS];
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ tmp[i] = gsl_histogram_get (h, i);
+ tmp[i] -= expected[i];
+ tmp[i] *= tmp[i];
+ tmp[i] /= expected[i];
+ }
+
+ gsl_histogram_free (h);
+
+ double chiSquared = 0;
+
+ for (uint32_t i = 0; i < N_BINS; ++i)
+ {
+ chiSquared += tmp[i];
+ }
+
+ return chiSquared;
+}
+
+void
+RandomVariableStreamErlangAntitheticTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double sum = 0.;
+ double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
+
+ for (uint32_t i = 0; i < N_RUNS; ++i)
+ {
+ Ptr<ErlangRandomVariable> n = CreateObject<ErlangRandomVariable> ();
+
+ // Make this generate antithetic values.
+ n->SetAttribute ("Antithetic", BooleanValue (true));
+
+ double result = ChiSquaredTest (n);
+ sum += result;
+ }
+
+ sum /= (double)N_RUNS;
+
+ NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
+
+ uint32_t k = 5;
+ double lambda = 2.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<ErlangRandomVariable> x = CreateObject<ErlangRandomVariable> ();
+
+ // Make this generate antithetic values.
+ x->SetAttribute ("Antithetic", BooleanValue (true));
+
+ x->SetAttribute ("K", IntegerValue (k));
+ x->SetAttribute ("Lambda", DoubleValue (lambda));
+
+ // Calculate the mean of these values.
+ sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean of the values returned by a
+ // Erlangly distributed random variable is equal to
+ //
+ // E[value] = k * lambda .
+ //
+ double expectedMean = k * lambda;
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = expectedMean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for Zipf distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamZipfTestCase : public TestCase
+{
+public:
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamZipfTestCase ();
+ virtual ~RandomVariableStreamZipfTestCase ();
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamZipfTestCase::RandomVariableStreamZipfTestCase ()
+ : TestCase ("Zipf Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamZipfTestCase::~RandomVariableStreamZipfTestCase ()
+{
+}
+
+void
+RandomVariableStreamZipfTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ uint32_t n = 1;
+ double alpha = 2.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<ZipfRandomVariable> x = CreateObject<ZipfRandomVariable> ();
+ x->SetAttribute ("N", IntegerValue (n));
+ x->SetAttribute ("Alpha", DoubleValue (alpha));
+
+ // Calculate the mean of these values.
+ double sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean of the values returned by a
+ // Zipfly distributed random variable is equal to
+ //
+ // H
+ // N, alpha - 1
+ // E[value] = ---------------
+ // H
+ // N, alpha
+ //
+ // where
+ //
+ // N
+ // ---
+ // \ -alpha
+ // H = / m .
+ // N, alpha ---
+ // m=1
+ //
+ // For this test,
+ //
+ // -(alpha - 1)
+ // 1
+ // E[value] = ---------------
+ // -alpha
+ // 1
+ //
+ // = 1 .
+ //
+ double expectedMean = 1.0;
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = expectedMean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for antithetic Zipf distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamZipfAntitheticTestCase : public TestCase
+{
+public:
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamZipfAntitheticTestCase ();
+ virtual ~RandomVariableStreamZipfAntitheticTestCase ();
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamZipfAntitheticTestCase::RandomVariableStreamZipfAntitheticTestCase ()
+ : TestCase ("Antithetic Zipf Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamZipfAntitheticTestCase::~RandomVariableStreamZipfAntitheticTestCase ()
+{
+}
+
+void
+RandomVariableStreamZipfAntitheticTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ uint32_t n = 1;
+ double alpha = 2.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<ZipfRandomVariable> x = CreateObject<ZipfRandomVariable> ();
+ x->SetAttribute ("N", IntegerValue (n));
+ x->SetAttribute ("Alpha", DoubleValue (alpha));
+
+ // Make this generate antithetic values.
+ x->SetAttribute ("Antithetic", BooleanValue (true));
+
+ // Calculate the mean of these values.
+ double sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean of the values returned by a
+ // Zipfly distributed random variable is equal to
+ //
+ // H
+ // N, alpha - 1
+ // E[value] = ---------------
+ // H
+ // N, alpha
+ //
+ // where
+ //
+ // N
+ // ---
+ // \ -alpha
+ // H = / m .
+ // N, alpha ---
+ // m=1
+ //
+ // For this test,
+ //
+ // -(alpha - 1)
+ // 1
+ // E[value] = ---------------
+ // -alpha
+ // 1
+ //
+ // = 1 .
+ //
+ double expectedMean = 1.0;
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = expectedMean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for Zeta distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamZetaTestCase : public TestCase
+{
+public:
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamZetaTestCase ();
+ virtual ~RandomVariableStreamZetaTestCase ();
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamZetaTestCase::RandomVariableStreamZetaTestCase ()
+ : TestCase ("Zeta Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamZetaTestCase::~RandomVariableStreamZetaTestCase ()
+{
+}
+
+void
+RandomVariableStreamZetaTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double alpha = 5.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<ZetaRandomVariable> x = CreateObject<ZetaRandomVariable> ();
+ x->SetAttribute ("Alpha", DoubleValue (alpha));
+
+ // Calculate the mean of these values.
+ double sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean of the values returned by a
+ // zetaly distributed random variable is equal to
+ //
+ // zeta(alpha - 1)
+ // E[value] = --------------- for alpha > 2 ,
+ // zeta(alpha)
+ //
+ // where zeta(alpha) is the Riemann zeta function.
+ //
+ // There are no simple analytic forms for the Riemann zeta function,
+ // which is why the gsl library is used in this test to calculate
+ // the known mean of the values.
+ double expectedMean = gsl_sf_zeta_int (alpha - 1) / gsl_sf_zeta_int (alpha);
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = expectedMean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for antithetic Zeta distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamZetaAntitheticTestCase : public TestCase
+{
+public:
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamZetaAntitheticTestCase ();
+ virtual ~RandomVariableStreamZetaAntitheticTestCase ();
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamZetaAntitheticTestCase::RandomVariableStreamZetaAntitheticTestCase ()
+ : TestCase ("Antithetic Zeta Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamZetaAntitheticTestCase::~RandomVariableStreamZetaAntitheticTestCase ()
+{
+}
+
+void
+RandomVariableStreamZetaAntitheticTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ double alpha = 5.0;
+ double value;
+
+ // Create the RNG with the specified range.
+ Ptr<ZetaRandomVariable> x = CreateObject<ZetaRandomVariable> ();
+ x->SetAttribute ("Alpha", DoubleValue (alpha));
+
+ // Make this generate antithetic values.
+ x->SetAttribute ("Antithetic", BooleanValue (true));
+
+ // Calculate the mean of these values.
+ double sum = 0.0;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean of the values returned by a
+ // zetaly distributed random variable is equal to
+ //
+ // zeta(alpha - 1)
+ // E[value] = --------------- for alpha > 2 ,
+ // zeta(alpha)
+ //
+ // where zeta(alpha) is the Riemann zeta function.
+ //
+ // There are no simple analytic forms for the Riemann zeta function,
+ // which is why the gsl library is used in this test to calculate
+ // the known mean of the values.
+ double expectedMean = gsl_sf_zeta_int (alpha - 1) / gsl_sf_zeta_int (alpha);
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = expectedMean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for deterministic random variable stream generator
+// ===========================================================================
+class RandomVariableStreamDeterministicTestCase : public TestCase
+{
+public:
+ static const double TOLERANCE = 1e-8;
+
+ RandomVariableStreamDeterministicTestCase ();
+ virtual ~RandomVariableStreamDeterministicTestCase ();
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamDeterministicTestCase::RandomVariableStreamDeterministicTestCase ()
+ : TestCase ("Deterministic Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamDeterministicTestCase::~RandomVariableStreamDeterministicTestCase ()
+{
+}
+
+void
+RandomVariableStreamDeterministicTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ Ptr<DeterministicRandomVariable> s = CreateObject<DeterministicRandomVariable> ();
+
+ // The following array should give the sequence
+ //
+ // 4, 4, 7, 7, 10, 10 .
+ //
+ double array1 [] = { 4, 4, 7, 7, 10, 10};
+ uint64_t count1 = 6;
+ s->SetValueArray (array1, count1);
+
+ double value;
+
+ // Test that the first sequence is correct.
+ value = s->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ_TOL (value, 4, TOLERANCE, "Sequence 1 value 1 wrong.");
+ value = s->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ_TOL (value, 4, TOLERANCE, "Sequence 1 value 2 wrong.");
+ value = s->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ_TOL (value, 7, TOLERANCE, "Sequence 1 value 3 wrong.");
+ value = s->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ_TOL (value, 7, TOLERANCE, "Sequence 1 value 4 wrong.");
+ value = s->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ_TOL (value, 10, TOLERANCE, "Sequence 1 value 5 wrong.");
+ value = s->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ_TOL (value, 10, TOLERANCE, "Sequence 1 value 6 wrong.");
+
+ // The following array should give the sequence
+ //
+ // 1000, 2000, 7, 7 .
+ //
+ double array2 [] = { 1000, 2000, 3000, 4000};
+ uint64_t count2 = 4;
+ s->SetValueArray (array2, count2);
+
+ // Test that the second sequence is correct.
+ value = s->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ_TOL (value, 1000, TOLERANCE, "Sequence 2 value 1 wrong.");
+ value = s->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ_TOL (value, 2000, TOLERANCE, "Sequence 2 value 2 wrong.");
+ value = s->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ_TOL (value, 3000, TOLERANCE, "Sequence 2 value 3 wrong.");
+ value = s->GetValue ();
+ NS_TEST_ASSERT_MSG_EQ_TOL (value, 4000, TOLERANCE, "Sequence 2 value 4 wrong.");
+ value = s->GetValue ();
+}
+
+// ===========================================================================
+// Test case for empirical distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamEmpiricalTestCase : public TestCase
+{
+public:
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamEmpiricalTestCase ();
+ virtual ~RandomVariableStreamEmpiricalTestCase ();
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamEmpiricalTestCase::RandomVariableStreamEmpiricalTestCase ()
+ : TestCase ("Empirical Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamEmpiricalTestCase::~RandomVariableStreamEmpiricalTestCase ()
+{
+}
+
+void
+RandomVariableStreamEmpiricalTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ // Create the RNG with a uniform distribution between 0 and 10.
+ Ptr<EmpiricalRandomVariable> x = CreateObject<EmpiricalRandomVariable> ();
+ x->CDF ( 0.0, 0.0);
+ x->CDF ( 5.0, 0.5);
+ x->CDF (10.0, 1.0);
+
+ // Calculate the mean of these values.
+ double sum = 0.0;
+ double value;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean of the values returned by this
+ // empirical distribution is the midpoint of the distribution
+ //
+ // E[value] = 5 .
+ //
+ double expectedMean = 5.0;
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = expectedMean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+// ===========================================================================
+// Test case for antithetic empirical distribution random variable stream generator
+// ===========================================================================
+class RandomVariableStreamEmpiricalAntitheticTestCase : public TestCase
+{
+public:
+ static const uint32_t N_MEASUREMENTS = 1000000;
+
+ RandomVariableStreamEmpiricalAntitheticTestCase ();
+ virtual ~RandomVariableStreamEmpiricalAntitheticTestCase ();
+
+private:
+ virtual void DoRun (void);
+};
+
+RandomVariableStreamEmpiricalAntitheticTestCase::RandomVariableStreamEmpiricalAntitheticTestCase ()
+ : TestCase ("EmpiricalAntithetic Random Variable Stream Generator")
+{
+}
+
+RandomVariableStreamEmpiricalAntitheticTestCase::~RandomVariableStreamEmpiricalAntitheticTestCase ()
+{
+}
+
+void
+RandomVariableStreamEmpiricalAntitheticTestCase::DoRun (void)
+{
+ SeedManager::SetSeed (time (0));
+
+ // Create the RNG with a uniform distribution between 0 and 10.
+ Ptr<EmpiricalRandomVariable> x = CreateObject<EmpiricalRandomVariable> ();
+ x->CDF ( 0.0, 0.0);
+ x->CDF ( 5.0, 0.5);
+ x->CDF (10.0, 1.0);
+
+ // Make this generate antithetic values.
+ x->SetAttribute ("Antithetic", BooleanValue (true));
+
+ // Calculate the mean of these values.
+ double sum = 0.0;
+ double value;
+ for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
+ {
+ value = x->GetValue ();
+ sum += value;
+ }
+ double valueMean = sum / N_MEASUREMENTS;
+
+ // The expected value for the mean of the values returned by this
+ // empirical distribution is the midpoint of the distribution
+ //
+ // E[value] = 5 .
+ //
+ double expectedMean = 5.0;
+
+ // Test that values have approximately the right mean value.
+ double TOLERANCE = expectedMean * 1e-2;
+ NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
+}
+
+class RandomVariableStreamTestSuite : public TestSuite
+{
+public:
+ RandomVariableStreamTestSuite ();
+};
+
+RandomVariableStreamTestSuite::RandomVariableStreamTestSuite ()
+ : TestSuite ("random-variable-stream-generators", UNIT)
+{
+ AddTestCase (new RandomVariableStreamUniformTestCase);
+ AddTestCase (new RandomVariableStreamUniformAntitheticTestCase);
+ AddTestCase (new RandomVariableStreamConstantTestCase);
+ AddTestCase (new RandomVariableStreamSequentialTestCase);
+ AddTestCase (new RandomVariableStreamNormalTestCase);
+ AddTestCase (new RandomVariableStreamNormalAntitheticTestCase);
+ AddTestCase (new RandomVariableStreamExponentialTestCase);
+ AddTestCase (new RandomVariableStreamExponentialAntitheticTestCase);
+ AddTestCase (new RandomVariableStreamParetoTestCase);
+ AddTestCase (new RandomVariableStreamParetoAntitheticTestCase);
+ AddTestCase (new RandomVariableStreamWeibullTestCase);
+ AddTestCase (new RandomVariableStreamWeibullAntitheticTestCase);
+ AddTestCase (new RandomVariableStreamLogNormalTestCase);
+ // XXX This test is currently disabled because it fails sometimes.
+ // A possible reason for the failure is that the antithetic code is
+ // not implemented properly for this log-normal case.
+ /*
+ AddTestCase (new RandomVariableStreamLogNormalAntitheticTestCase);
+ */
+ AddTestCase (new RandomVariableStreamGammaTestCase);
+ // XXX This test is currently disabled because it fails sometimes.
+ // A possible reason for the failure is that the antithetic code is
+ // not implemented properly for this gamma case.
+ /*
+ AddTestCase (new RandomVariableStreamGammaAntitheticTestCase);
+ */
+ AddTestCase (new RandomVariableStreamErlangTestCase);
+ AddTestCase (new RandomVariableStreamErlangAntitheticTestCase);
+ AddTestCase (new RandomVariableStreamZipfTestCase);
+ AddTestCase (new RandomVariableStreamZipfAntitheticTestCase);
+ AddTestCase (new RandomVariableStreamZetaTestCase);
+ AddTestCase (new RandomVariableStreamZetaAntitheticTestCase);
+ AddTestCase (new RandomVariableStreamDeterministicTestCase);
+ AddTestCase (new RandomVariableStreamEmpiricalTestCase);
+ AddTestCase (new RandomVariableStreamEmpiricalAntitheticTestCase);
+}
+
+static RandomVariableStreamTestSuite randomVariableStreamTestSuite;
--- a/src/core/wscript Sun Jul 29 14:29:41 2012 +0200
+++ b/src/core/wscript Tue Jul 31 19:18:23 2012 +0200
@@ -124,6 +124,8 @@
'model/object.cc',
'model/test.cc',
'model/random-variable.cc',
+ 'model/random-variable-stream.cc',
+ 'model/rng-seed-manager.cc',
'model/rng-stream.cc',
'model/command-line.cc',
'model/type-name.cc',
@@ -206,6 +208,8 @@
'model/fatal-error.h',
'model/test.h',
'model/random-variable.h',
+ 'model/random-variable-stream.h',
+ 'model/rng-seed-manager.h',
'model/rng-stream.h',
'model/command-line.h',
'model/type-name.h',
--- a/src/csma/helper/csma-helper.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/csma/helper/csma-helper.h Tue Jul 31 19:18:23 2012 +0200
@@ -222,6 +222,7 @@
* \param stream The output stream object to use when logging ascii traces.
* \param prefix Filename prefix to use for ascii trace files.
* \param nd Net device for which you want to enable tracing.
+ * \param explicitFilename Treat the prefix as an explicit filename if true
*/
virtual void EnableAsciiInternal (Ptr<OutputStreamWrapper> stream,
std::string prefix,
--- a/src/emu/helper/emu-helper.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/emu/helper/emu-helper.h Tue Jul 31 19:18:23 2012 +0200
@@ -138,6 +138,7 @@
* \param stream The output stream object to use when logging ascii traces.
* \param prefix Filename prefix to use for ascii trace files.
* \param nd Net device for which you want to enable tracing.
+ * \param explicitFilename Treat the prefix as an explicit filename if true
*/
virtual void EnableAsciiInternal (Ptr<OutputStreamWrapper> stream,
std::string prefix,
--- a/src/energy/helper/wifi-radio-energy-model-helper.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/energy/helper/wifi-radio-energy-model-helper.h Tue Jul 31 19:18:23 2012 +0200
@@ -66,6 +66,7 @@
private:
/**
* \param device Pointer to the NetDevice to install DeviceEnergyModel.
+ * \param source Pointer to EnergySource to install.
*
* Implements DeviceEnergyModel::Install.
*/
--- a/src/energy/model/wifi-radio-energy-model.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/energy/model/wifi-radio-energy-model.h Tue Jul 31 19:18:23 2012 +0200
@@ -229,7 +229,7 @@
virtual double DoGetCurrentA (void) const;
/**
- * \param currentState New state the radio device is currently in.
+ * \param state New state the radio device is currently in.
*
* Sets current state. This function is private so that only the energy model
* can change its own state.
--- a/src/energy/test/rv-battery-model-test.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/energy/test/rv-battery-model-test.cc Tue Jul 31 19:18:23 2012 +0200
@@ -76,7 +76,7 @@
/**
* \param loads Load profile.
* \param timeStamps Time stamps.
- * \param expLifeTime Expected lifetime.
+ * \param expLifetime Expected lifetime.
* \returns False if no error occurs.
*
* Runs simulation with variable load and checks the battery lifetime with
--- a/src/internet/helper/internet-stack-helper.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/internet/helper/internet-stack-helper.h Tue Jul 31 19:18:23 2012 +0200
@@ -186,6 +186,7 @@
* @param prefix Filename prefix to use for pcap files.
* @param ipv4 Ptr to the Ipv4 interface on which you want to enable tracing.
* @param interface Interface ID on the Ipv4 on which you want to enable tracing.
+ * @param explicitFilename Treat the prefix as an explicit filename if true
*/
virtual void EnablePcapIpv4Internal (std::string prefix,
Ptr<Ipv4> ipv4,
@@ -201,6 +202,7 @@
* @param prefix Filename prefix to use for ascii trace files.
* @param ipv4 Ptr to the Ipv4 interface on which you want to enable tracing.
* @param interface Interface ID on the Ipv4 on which you want to enable tracing.
+ * @param explicitFilename Treat the prefix as an explicit filename if true
*/
virtual void EnableAsciiIpv4Internal (Ptr<OutputStreamWrapper> stream,
std::string prefix,
@@ -215,6 +217,7 @@
* @param prefix Filename prefix to use for pcap files.
* @param ipv6 Ptr to the Ipv6 interface on which you want to enable tracing.
* @param interface Interface ID on the Ipv6 on which you want to enable tracing.
+ * @param explicitFilename Treat the prefix as an explicit filename if true
*/
virtual void EnablePcapIpv6Internal (std::string prefix,
Ptr<Ipv6> ipv6,
@@ -230,6 +233,7 @@
* @param prefix Filename prefix to use for ascii trace files.
* @param ipv6 Ptr to the Ipv6 interface on which you want to enable tracing.
* @param interface Interface ID on the Ipv6 on which you want to enable tracing.
+ * @param explicitFilename Treat the prefix as an explicit filename if true
*/
virtual void EnableAsciiIpv6Internal (Ptr<OutputStreamWrapper> stream,
std::string prefix,
--- a/src/internet/model/global-route-manager-impl.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/internet/model/global-route-manager-impl.h Tue Jul 31 19:18:23 2012 +0200
@@ -336,8 +336,6 @@
* @see GlobalRouter
* @see GlobalRoutingLSA
* @see GlobalRoutingLinkRecord
- * @param nextHop The IP address to use when forwarding packets to the host
- * or network represented by "this" SPFVertex.
* @param exit The pair of next-hop-IP and outgoing-interface-index to use when
* forwarding packets to the host or network represented by "this" SPFVertex.
*/
--- a/src/lte/doc/Makefile Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/doc/Makefile Tue Jul 31 19:18:23 2012 +0200
@@ -24,10 +24,10 @@
$(FIGURES)/lte-ue-phy.dia \
$(FIGURES)/lte-epc-e2e-data-protocol-stack.dia \
$(FIGURES)/lte-interference-test-scenario.dia \
+ $(FIGURES)/lte-subframe-structure.dia \
$(FIGURES)/lte-epc-x2-interface.dia
-
# specify eps figures from which .png and .pdf figures need to be built
IMAGES_EPS = \
@@ -78,6 +78,7 @@
$(FIGURES)/rrc-connection-establishment.pdf_width = 9cm
$(FIGURES)/rrc-connection-reconfiguration-handover.pdf_width = 11cm
$(FIGURES)/auvmobility-classes.pdf_width = 10cm
+$(FIGURES)/lte-subframe-structure.pdf_width = 2in
IMAGES_SEQDIAG = \
Binary file src/lte/doc/source/figures/lte-phy-interference.pdf has changed
Binary file src/lte/doc/source/figures/lte-phy-interference.png has changed
Binary file src/lte/doc/source/figures/lte-subframe-structure.dia has changed
--- a/src/lte/doc/source/figures/rrc-connection-reconfiguration-handover.seqdiag Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/doc/source/figures/rrc-connection-reconfiguration-handover.seqdiag Tue Jul 31 19:18:23 2012 +0200
@@ -28,22 +28,10 @@
UeMac <<- UePhy [label="Rx RAR"]
UeRrc <<- UeMac [label="NotifyRandomAccessProcedureEndOk"]
=== end non-contention based MAC Random Access Procedure ===
- UeMac ->> UePhy [label="SendOverUlsch (RrcConnectionReestablishmentRequest)"]
+ UeMac ->> UePhy [label="SendOverUlsch (RrcConnectionReconfigurationCompleted)"]
UePhy ->> EnbPhy [label="TX over PUSCH"]
- EnbPhy ->> EnbMac [label="RxOverUlsch (RrcConnectionReestablishmentRequest)"]
- EnbMac ->> EnbRrc [label="RxOverCcch (RrcConnectionReestablishmentRequest, T-C-RNTI)"]
- EnbMac <<- EnbRrc [label="SendOverCcch (RrcConnectionReestablishment)"]
- EnbMac ->> FfSched [label="SCHED_DL_RLC_BUFFER_REQ"]
- EnbPhy ->> EnbMac [label="SubframeIndication"]
- EnbMac ->> FfSched [label="SCHED_DL_TRIGGER_REQ"]
- EnbMac <<- FfSched [label="SCHED_DL_CONFIG_IND (DATA list)"]
- EnbPhy <<- EnbMac [label="Send PDU"]
- UePhy <<- EnbPhy [label="PDU over DL-SCH"]
- UeMac <<- UePhy [label="Rx PDU"]
- UeRrc <<- UeMac [label="RxOverCcch (RrcConnectionReestablishment)"]
- UeRrc ->> EnbRrc [label="RrcConnectionReestablishmentCompleted over SRB1)"]
-
-
+ EnbPhy ->> EnbMac [label="RxOverUlsch (RrcConnectionReconfigurationCompleted)"]
+ EnbMac ->> EnbRrc [label="RxOverCcch (RrcConnectionReconfigurationCompleted)"]
}
--- a/src/lte/doc/source/lte-design.rst Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/doc/source/lte-design.rst Tue Jul 31 19:18:23 2012 +0200
@@ -285,7 +285,7 @@
.. figure:: figures/epc-data-flow-dl.*
:align: center
- Data flow in the dowlink between the internet and the UE
+ Data flow in the downlink between the internet and the UE
To begin with, we consider the case of the downlink, which is depicted
in Figure :ref:`fig-epc-data-flow-dl`.
@@ -523,7 +523,7 @@
For certain bandwidth
values not all the RBs are usable, since the
group size is not a common divisor of the group. This is for instance the case
-when the bandwith is equal to 25 RBs, which results in a RBG size of 2 RBs, and
+when the bandwidth is equal to 25 RBs, which results in a RBG size of 2 RBs, and
therefore 1 RB will result not addressable.
In uplink the format of the DCIs is different, since only adjacent RBs
can be used because of the SC-FDMA modulation. As a consequence, all
@@ -1304,6 +1304,26 @@
inter cell intereference calculation and the simulation of uplink traffic, including both packet transmission and CQI generation.
+Subframe Structure
+^^^^^^^^^^^^^^^^^^
+
+The subframe is divided into control and data part as described in Figure :ref:`fig-lte-subframe-structure`.
+
+.. _fig-lte-subframe-structure:
+
+.. figure:: figures/lte-subframe-structure.*
+ :width: 50px
+
+ Lte subframe division.
+
+
+Considering the granularity of the simulator based on RB, the control and the reference signaling have to be consequently modeled considering this constraint. According to the standard [TS36.211]_, the downlink control frame starts at the beginning of each subframe and lasts up to three symbols across the whole system bandwidth, where the actual duration is provided by the Physical Control Format Indicator Channel (PCFICH). The information on the allocation are then mapped in the remaining resource up to the duration defined by the PCFICH, in the so called Physical Downlink Control Channel (PDCCH). A PDCCH transports a single message called Downlink Control Information (DCI) coming from the MAC layer, where the scheduler indicates the resource allocation for a specific user.
+The PCFICH and PDCCH are modeled with the transmission of the control frame of a fixed duration of 3/14 of milliseconds spanning in the whole available bandwidth, since the scheduler does not estimate the size of the control region. This implies that a single transmission block models the entire control frame with a fixed power (i.e., the one used for the PDSCH) across all the available RBs. According to this feature, this transmission represents also a valuable support for the Reference Signal (RS). This allows of having every TTI an evaluation of the interference scenario since all the eNB are transmitting (simultaneously) the control frame over the respective available bandwidths. We note that, the model does not include the power boosting since it does not reflect any improvement in the implemented model of the channel estimation.
+
+
+The Sounding Reference Signal (SRS) is modeled similar to the downlink control frame. The SRS is periodically placed in the last symbol of the subframe in the whole system bandwidth. The RRC module already includes an algorithm for dynamically assigning the periodicity as function of the actual number of UEs attached to a eNB according to the UE-specific procedure (see Section 8.2 of [TS36.213]_).
+
+
MAC to Channel delay
^^^^^^^^^^^^^^^^^^^^
@@ -1357,10 +1377,10 @@
-PHY Error Model
----------------
-
-The simulator includes an error model of the data plane (i.e., PDSCH) according to the standard link-to-system mapping (LSM) techniques. The choice is aligned with the standard system simulation methodology of OFDMA radio transmission technology. Thanks to LSM we are able to maintain a good level of accuracy and at the same time limiting the computational complexity increase. It is based on the mapping of single link layer performance obtained by means of link level simulators to system (in our case network) simulators. In particular link the layer simulator is used for generating the performance of a single link from a PHY layer perspective, usually in terms of code block error rate (BLER), under specific static conditions. LSM allows the usage of these parameters in more complex scenarios, typical of system/network simulators, where we have more links, interference and "colored" channel propagation phenomena (e.g., frequency selective fading).
+Data PHY Error Model
+--------------------
+
+The simulator includes an error model of the data plane (i.e., PDSCH and PUSCH) according to the standard link-to-system mapping (LSM) techniques. The choice is aligned with the standard system simulation methodology of OFDMA radio transmission technology. Thanks to LSM we are able to maintain a good level of accuracy and at the same time limiting the computational complexity increase. It is based on the mapping of single link layer performance obtained by means of link level simulators to system (in our case network) simulators. In particular link the layer simulator is used for generating the performance of a single link from a PHY layer perspective, usually in terms of code block error rate (BLER), under specific static conditions. LSM allows the usage of these parameters in more complex scenarios, typical of system/network simulators, where we have more links, interference and "colored" channel propagation phenomena (e.g., frequency selective fading).
To do this the Vienna LTE Simulator [ViennaLteSim]_ has been used for what concerns the extraction of link layer performance and the Mutual Information Based Effective SINR (MIESM) as LSM mapping function using part of the work recently published by the Signet Group of University of Padua [PaduaPEM]_.
@@ -1497,8 +1517,20 @@
The model can be disabled for working with a zero-losses channel by setting the ``PemEnabled`` attribute of the ``LteSpectrumPhy`` class (by default is active). This can be done according to the standard ns3 attribute system procedure, that is::
- Config::SetDefault ("ns3::LteSpectrumPhy::PemEnabled", BooleanValue (false));
-
+ Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
+
+Control Channels PHY Error Model
+--------------------------------
+
+The simulator includes the error model for downlink control channels (PCFICH and PDCCH), while in uplink it is assumed and ideal error-free channel. The model is based on the MIESM approach presented before for considering the effects of the frequency selective channel since most of the control channels span the whole available bandwidth.
+
+
+PCFICH + PDCCH Error Model
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The model adopted for the error distribution of these channels is based on an evaluation study carried out in the RAN4 of 3GPP, where different vendors investigated the demodulation performance of the PCFICH jointly with PDCCH. This is due to the fact that the PCFICH is the channel in charge of communicating to the UEs the actual dimension of the PDCCH (which spans between 1 and 3 symbols); therefore the correct decodification of the DCIs depends on the correct interpretation of both ones. In 3GPP this problem have been evaluated for improving the cell-edge performance _[FujitsuWhitePaper], where the interference among neighboring cells can be relatively high due to signal degradation. A similar problem has been notices in femto-cell scenario and, more in general, in HetNet scenarios the bottleneck has been detected mainly as the PCFICH channel _[Bharucha2011], where in case of many eNBs are deployed in the same service area, this channel may collide in frequency, making impossible the correct detection of the PDCCH channel, too.
+
+In the simulator, the SINR perceived during the reception has been estimated according to the MIESM model presented above in order to evaluate the error distribution of PCFICH and PDCCH. In detail, the SINR samples of all the RBs are included in the evaluation of the MI associated to the control frame and, according to this values, the effective SINR (eSINR) is obtained by inverting the MI evaluation process. It has to be noted that, in case of MIMO transmission, both PCFICH and the PDCCH use always the transmit diversity mode as defined by the standard. According to the eSINR perceived the decodification error probability can be estimated as function of the results presented in _[R4-081920]. In case an error occur, the DCIs discarded and therefore the UE will be not able to receive the correspondent Tbs, therefore resulting lost.
MIMO Model
--- a/src/lte/doc/source/lte-references.rst Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/doc/source/lte-references.rst Tue Jul 31 19:18:23 2012 +0200
@@ -83,3 +83,15 @@
.. [Ikuno2010] J.C. Ikuno, M. Wrulich, M. Rupp, "System Level Simulation of LTE Networks," Vehicular Technology Conference (VTC 2010-Spring), 2010 IEEE 71st , vol., no., pp.1-5, 16-19 May 2010
+.. [Milos2012] J. Milos, "Performace Analysis Of PCFICH LTE Control Channel", Proceedings of the 19th Conference STUDENT EEICT 2012, Brno, CZ, 2012.
+
+.. [FujitsuWhitePaper] "Enhancing LTE Cell-Edge Performance via PDCCH ICIC".
+
+
+.. [Bharucha2011] Z. Bharucha, G. Auer, T. Abe, N. Miki, "Femto-to-Macro Control Channel Interference Mitigation via Cell ID Manipulation in LTE," Vehicular Technology Conference (VTC Fall), 2011 IEEE , vol., no., pp.1-6, 5-8 Sept. 2011
+
+.. [R4-081920] 3GPP R4-081920 `LTE PDCCH/PCFICH Demodulation Performance Results with Implementation Margin
+ <http://www.3gpp.org/ftp/tsg_ran/wg4_radio/TSGR4_48/Documents/R4-081920.zip>`_
+
+
+
--- a/src/lte/doc/source/lte-testing.rst Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/doc/source/lte-testing.rst Tue Jul 31 19:18:23 2012 +0200
@@ -368,7 +368,7 @@
--------------------
-The test suite ``lte-test-phy-error-model`` generates nine test cases with single eNB and a various number of UEs, all having the same Radio Bearer specification. Each test is designed for evaluating the error rate perceived by a specific TB size in order to verify that it corresponds to the expected values according to the BLER generated for CB size analog to the TB size. This means that, for instance, the test will check that the performance of a TB of :math:`N` bits is analogous to the one of a a CB size of :math:`N` bits by collecting the performance of a user which has been forced the generation of a such TB size according to the distance to eNB. In order to significantly test the BER at MAC level, we modified the Adaptive Modulation and Coding (AMC) module, the ``LteAmc`` class, for making it less robust to channel conditions by adding a configurable BER parameter (called ``Ber`` in the ns3 attribute system) which enable the selection of the desired BER at MAC level when choosing the MCS to be used. In detail, the AMC module has been forced to select the AMC considering a BER of 0.01 (instead of the standard value equal to 0.00005). We note that, these values do not reflect actual BER since they come from an analytical bound which do not consider all the transmission chain aspects; therefore the resulted BER might be different.
+The test suite ``lte-phy-error-model`` generates different test cases for evaluating both data and control error models. For what concern the data, the test consists of nine test cases with single eNB and a various number of UEs, all having the same Radio Bearer specification. Each test is designed for evaluating the error rate perceived by a specific TB size in order to verify that it corresponds to the expected values according to the BLER generated for CB size analog to the TB size. This means that, for instance, the test will check that the performance of a TB of :math:`N` bits is analogous to the one of a a CB size of :math:`N` bits by collecting the performance of a user which has been forced the generation of a such TB size according to the distance to eNB. In order to significantly test the BER at MAC level, we modified the Adaptive Modulation and Coding (AMC) module, the ``LteAmc`` class, for making it less robust to channel conditions by adding a configurable BER parameter (called ``Ber`` in the ns3 attribute system) which enable the selection of the desired BER at MAC level when choosing the MCS to be used. In detail, the AMC module has been forced to select the AMC considering a BER of 0.01 (instead of the standard value equal to 0.00005). We note that, these values do not reflect actual BER since they come from an analytical bound which do not consider all the transmission chain aspects; therefore the resulted BER might be different.
The parameters of the nine test cases are reported in the following:
@@ -403,7 +403,15 @@
BLER for test 6.
-The test verifies that in each case the obtained number of packets received correctly falls within the 95% confidence interval of a Binomial distribution where the parameter :math:`p` is equal to :math:`1-BER`, the parameter :math:`n` is the total number of packets sent and the parameter :math:`k` is the number of packets correctly received.
+The test verifies that in each case the expected number of packets received correct corresponds to a Bernoulli distribution with a confidence interval of 95%, where the probability of success in each trail is :math:`1-BER` and :math:`n` is the total number of packet sent.
+
+The error model of PCFICH-PDDCH channels consists of 4 test cases with a single UE and several eNBs, where the UE is connected to only one eNB in order to have the remaining acting as interfering ones. The errors on data are disabled in order to verify only the ones due to erroneous decodification of PCFICH-PDCCH. The test verifies that the error on the data received respects the decodification error probability of the PCFICH-PDCCH with a tolerance of 0.1 due to the errors that might be produced in quantizing the MI and the error curve. As before, the system has been forced on working in a less conservative fashion in the AMC module for appreciating the results in border situations. The parameters of the 4 tests cases are reported in the following:
+
+ #. 2 eNBs placed 1078 meters far from the UE, which implies a SINR of -2.00 dB and a TB of 217 bits, that in turns produce a BER of 0.007.
+ #. 3 eNBs placed 1078 meters far from the UE, which implies a SINR of -4.00 dB and a TB of 217 bits, that in turns produce a BER of 0.045.
+ #. 4 eNBs placed 1078 meters far from the UE, which implies a SINR of -6.00 dB and a TB of 133 bits, that in turns produce a BER of 0.206.
+ #. 5 eNBs placed 1078 meters far from the UE, which implies a SINR of -7.00 dB and a TB of 81 bits, that in turns produce a BER of 0.343.
+
MIMO Model
--- a/src/lte/doc/source/lte-user.rst Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/doc/source/lte-user.rst Tue Jul 31 19:18:23 2012 +0200
@@ -438,6 +438,16 @@
This command will go through the lists of all nodes and of all buildings, determine for each user if it is indoor or outdoor, and if indoor it will also determine the building in which the user is located and the corresponding floor and number inside the building.
+PHY Error Model
+---------------
+
+The Physical error model consists of the data error model and the downlink control error model, both of them active by default. It is possible to deactivate them with the ns3 attribute system, in detail::
+
+ Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+ Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
+
+
+
MIMO Model
----------
--- a/src/lte/examples/lena-dual-stripe.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/examples/lena-dual-stripe.cc Tue Jul 31 19:18:23 2012 +0200
@@ -215,6 +215,115 @@
}
}
+
+static ns3::GlobalValue g_nBlocks ("nBlocks",
+ "Number of femtocell blocks",
+ ns3::UintegerValue (10),
+ ns3::MakeUintegerChecker<uint32_t> ());
+static ns3::GlobalValue g_nApartmentsX ("nApartmentsX",
+ "Number of apartments along the X axis in a femtocell block",
+ ns3::UintegerValue (10),
+ ns3::MakeUintegerChecker<uint32_t> ());
+static ns3::GlobalValue g_nFloors ("nFloors",
+ "Number of floors",
+ ns3::UintegerValue (1),
+ ns3::MakeUintegerChecker<uint32_t> ());
+static ns3::GlobalValue g_nMacroEnbSites ("nMacroEnbSites",
+ "How many macro sites there are",
+ ns3::UintegerValue (3),
+ ns3::MakeUintegerChecker<uint32_t> ());
+static ns3::GlobalValue g_nMacroEnbSitesX ("nMacroEnbSitesX",
+ "(minimum) number of sites along the X-axis of the hex grid",
+ ns3::UintegerValue (1),
+ ns3::MakeUintegerChecker<uint32_t> ());
+static ns3::GlobalValue g_interSiteDistance ("interSiteDistance",
+ "min distance between two nearby macro cell sites",
+ ns3::DoubleValue (500),
+ ns3::MakeDoubleChecker<double> ());
+static ns3::GlobalValue g_areaMarginFactor ("areaMarginFactor",
+ "how much the UE area extends outside the macrocell grid, "
+ "expressed as fraction of the interSiteDistance",
+ ns3::DoubleValue (0.5),
+ ns3::MakeDoubleChecker<double> ());
+static ns3::GlobalValue g_macroUeDensity ("macroUeDensity",
+ "How many macrocell UEs there are per square meter",
+ ns3::DoubleValue (0.0001),
+ ns3::MakeDoubleChecker<double> ());
+static ns3::GlobalValue g_homeEnbDeploymentRatio ("homeEnbDeploymentRatio",
+ "The HeNB deployment ratio as per 3GPP R4-092042",
+ ns3::DoubleValue (0.2),
+ ns3::MakeDoubleChecker<double> ());
+static ns3::GlobalValue g_homeEnbActivationRatio ("homeEnbActivationRatio",
+ "The HeNB activation ratio as per 3GPP R4-092042",
+ ns3::DoubleValue (0.5),
+ ns3::MakeDoubleChecker<double> ());
+static ns3::GlobalValue g_homeUesHomeEnbRatio ("homeUesHomeEnbRatio",
+ "How many (on average) home UEs per HeNB there are in the simulation",
+ ns3::DoubleValue (1.0),
+ ns3::MakeDoubleChecker<double> ());
+static ns3::GlobalValue g_macroEnbTxPowerDbm ("macroEnbTxPowerDbm",
+ "TX power [dBm] used by macro eNBs",
+ ns3::DoubleValue (46.0),
+ ns3::MakeDoubleChecker<double> ());
+static ns3::GlobalValue g_homeEnbTxPowerDbm ("homeEnbTxPowerDbm",
+ "TX power [dBm] used by HeNBs",
+ ns3::DoubleValue (20.0),
+ ns3::MakeDoubleChecker<double> ());
+static ns3::GlobalValue g_macroEnbDlEarfcn ("macroEnbDlEarfcn",
+ "DL EARFCN used by macro eNBs",
+ ns3::UintegerValue (100),
+ ns3::MakeUintegerChecker<uint16_t> ());
+static ns3::GlobalValue g_homeEnbDlEarfcn ("homeEnbDlEarfcn",
+ "DL EARFCN used by HeNBs",
+ ns3::UintegerValue (100),
+ ns3::MakeUintegerChecker<uint16_t> ());
+static ns3::GlobalValue g_macroEnbBandwidth ("macroEnbBandwidth",
+ "bandwdith [num RBs] used by macro eNBs",
+ ns3::UintegerValue (25),
+ ns3::MakeUintegerChecker<uint16_t> ());
+static ns3::GlobalValue g_homeEnbBandwidth ("homeEnbBandwidth",
+ "bandwdith [num RBs] used by HeNBs",
+ ns3::UintegerValue (25),
+ ns3::MakeUintegerChecker<uint16_t> ());
+static ns3::GlobalValue g_simTime ("simTime",
+ "Total duration of the simulation [s]",
+ ns3::DoubleValue (0.25),
+ ns3::MakeDoubleChecker<double> ());
+static ns3::GlobalValue g_generateRem ("generateRem",
+ "if true, will generate a REM and then abort the simulation;"
+ "if false, will run the simulation normally (without generating any REM)",
+ ns3::BooleanValue (false),
+ ns3::MakeBooleanChecker ());
+static ns3::GlobalValue g_epc ("epc",
+ "if true, will setup the EPC to simulate an end-to-end topology;"
+ "if false, only the LTE radio access will be simulated.",
+ ns3::BooleanValue (false),
+ ns3::MakeBooleanChecker ());
+static ns3::GlobalValue g_epcDl ("epcDl",
+ "if true, will activate data flows in the downlink when EPC is being used. "
+ "If false, downlink flows won't be activated. "
+ "If EPC is not used, this parameter will be ignored.",
+ ns3::BooleanValue (true),
+ ns3::MakeBooleanChecker ());
+static ns3::GlobalValue g_epcUl ("epcUl",
+ "if true, will activate data flows in the uplink when EPC is being used. "
+ "If false, uplink flows won't be activated. "
+ "If EPC is not used, this parameter will be ignored.",
+ ns3::BooleanValue (true),
+ ns3::MakeBooleanChecker ());
+static ns3::GlobalValue g_useUdp ("useUdp",
+ "if true, the UdpClient application will be used. "
+ "Otherwise, the BulkSend application will be used over a TCP connection. "
+ "If EPC is not used, this parameter will be ignored.",
+ ns3::BooleanValue (true),
+ ns3::MakeBooleanChecker ());
+static ns3::GlobalValue g_fadingTrace ("fadingTrace",
+ "The path of the fading trace (by default no fading trace "
+ "is loaded, i.e., fading is not considered)",
+ ns3::StringValue (""),
+ ns3::MakeStringChecker ());
+
+
int
main (int argc, char *argv[])
{
@@ -224,79 +333,66 @@
Config::SetDefault ("ns3::UdpClient::Interval", TimeValue (MilliSeconds(1)));
Config::SetDefault ("ns3::UdpClient::MaxPackets", UintegerValue(1000000));
- // scenario parameters
- uint32_t nBlocks = 10;
- uint32_t nApartmentsX = 10;
- uint32_t nFloors = 1;
- uint32_t nMacroEnbSites = 3;
- uint32_t nMacroEnbSitesX = 1;
- double interSiteDistance = 500;
- double areaMarginFactor = 0.5;
- double macroUeDensity = 0.0001;
- double homeEnbDeploymentRatio = 0.2;
- double homeEnbActivationRatio = 0.5;
- double homeUesHomeEnbRatio = 1;
- double macroEnbTxPowerDbm = 46.0;
- double homeEnbTxPowerDbm = 20.0;
- uint16_t macroEnbDlEarfcn = 100;
- uint16_t homeEnbDlEarfcn = 100;
- uint16_t macroEnbBandwidth = 25;
- uint16_t homeEnbBandwidth = 25;
- double simTime = 0.25;
- bool epc = false;
- bool epcDl = true;
- bool epcUl = true;
- bool useUdp = true;
- bool generateRem = false;
- std::string fadingFileTrace = "";
-
CommandLine cmd;
- cmd.AddValue ("nBlocks", "Number of femtocell blocks", nBlocks);
- cmd.AddValue ("nApartmentsX", "Number of apartments along the X axis in a femtocell block", nApartmentsX);
- cmd.AddValue ("nFloors", "Number of floors", nFloors);
- cmd.AddValue ("nMacroEnbSites", "How many macro sites there are", nMacroEnbSites);
- cmd.AddValue ("nMacroEnbSitesX",
- "(minimum) number of sites along the X-axis of the hex grid", nMacroEnbSitesX);
- cmd.AddValue ("interSiteDistance", "min distance between two nearby macro cell sites", interSiteDistance);
- cmd.AddValue ("areaMarginFactor", "how much the UE area extends outside the macrocell grid, "
- "expressed as fraction of the interSiteDistance", areaMarginFactor);
- cmd.AddValue ("macroUeDensity", "How many macrocell UEs there are per square meter", macroUeDensity);
- cmd.AddValue ("homeEnbDeploymentRatio",
- "The HeNB deployment ratio as per 3GPP R4-092042", homeEnbDeploymentRatio);
- cmd.AddValue ("homeEnbActivationRatio",
- "The HeNB activation ratio as per 3GPP R4-092042", homeEnbActivationRatio);
- cmd.AddValue ("homeUesHomeEnbRatio",
- "How many (on average) home UEs per HeNB there are in the simulation",
- homeUesHomeEnbRatio);
- cmd.AddValue ("macroEnbTxPowerDbm", "TX power [dBm] used by macro eNBs", macroEnbTxPowerDbm);
- cmd.AddValue ("homeEnbTxPowerDbm", "TX power [dBm] used by HeNBs", homeEnbTxPowerDbm);
- cmd.AddValue ("macroEnbDlEarfcn", "DL EARFCN used by macro eNBs", macroEnbDlEarfcn);
- cmd.AddValue ("homeEnbDlEarfcn", "DL EARFCN used by HeNBs", homeEnbDlEarfcn);
- cmd.AddValue ("macroEnbBandwidth", "bandwdith [num RBs] used by macro eNBs", macroEnbBandwidth);
- cmd.AddValue ("homeEnbBandwidth", "bandwdith [num RBs] used by HeNBs", homeEnbBandwidth);
- cmd.AddValue ("simTime", "Total duration of the simulation [s]", simTime);
- cmd.AddValue ("generateRem", "if true, will generate a REM and then abort the simulation;"
- "if false, will run the simulation normally (without generating any REM)", generateRem);
- cmd.AddValue ("epc", "if true, will setup the EPC to simulate an end-to-end topology;"
- "if false, only the LTE radio access will be simulated.", epc);
- cmd.AddValue ("epcDl", "if true, will activate data flows in the downlink when EPC is being used. "
- "If false, downlink flows won't be activated. "
- "If EPC is not used, this parameter will be ignored.", epcDl);
- cmd.AddValue ("epcUl", "if true, will activate data flows in the uplink when EPC is being used. "
- "If false, uplink flows won't be activated. "
- "If EPC is not used, this parameter will be ignored.", epcUl);
- cmd.AddValue ("useUdp", "if true, the UdpClient application will be used. "
- "Otherwise, the BulkSend application will be used over a TCP connection. "
- "If EPC is not used, this parameter will be ignored.", useUdp);
- cmd.AddValue ("fadingTrace", "The path of the fading trace (by default any fading trace is loadedm which implies that fading is not considered)", fadingFileTrace);
-
-
cmd.Parse (argc, argv);
-
ConfigStore inputConfig;
inputConfig.ConfigureDefaults ();
+ // parse again so you can override input file default values via command line
+ cmd.Parse (argc, argv);
- cmd.Parse (argc, argv);
+ // the scenario parameters get their values from the global attributes definde above
+ UintegerValue uintegerValue;
+ DoubleValue doubleValue;
+ BooleanValue booleanValue;
+ StringValue stringValue;
+ GlobalValue::GetValueByName ("nBlocks", uintegerValue);
+ uint32_t nBlocks = uintegerValue.Get ();
+ GlobalValue::GetValueByName ("nApartmentsX", uintegerValue);
+ uint32_t nApartmentsX = uintegerValue.Get ();
+ GlobalValue::GetValueByName ("nFloors", uintegerValue);
+ uint32_t nFloors = uintegerValue.Get ();
+ GlobalValue::GetValueByName ("nMacroEnbSites", uintegerValue);
+ uint32_t nMacroEnbSites = uintegerValue.Get ();
+ GlobalValue::GetValueByName ("nMacroEnbSitesX", uintegerValue);
+ uint32_t nMacroEnbSitesX = uintegerValue.Get ();
+ GlobalValue::GetValueByName ("interSiteDistance", doubleValue);
+ double interSiteDistance = doubleValue.Get ();
+ GlobalValue::GetValueByName ("areaMarginFactor", doubleValue);
+ double areaMarginFactor = doubleValue.Get ();
+ GlobalValue::GetValueByName ("macroUeDensity", doubleValue);
+ double macroUeDensity = doubleValue.Get ();
+ GlobalValue::GetValueByName ("homeEnbDeploymentRatio", doubleValue);
+ double homeEnbDeploymentRatio = doubleValue.Get ();
+ GlobalValue::GetValueByName ("homeEnbActivationRatio", doubleValue);
+ double homeEnbActivationRatio = doubleValue.Get ();
+ GlobalValue::GetValueByName ("homeUesHomeEnbRatio", doubleValue);
+ double homeUesHomeEnbRatio = doubleValue.Get ();
+ GlobalValue::GetValueByName ("macroEnbTxPowerDbm", doubleValue);
+ double macroEnbTxPowerDbm = doubleValue.Get ();
+ GlobalValue::GetValueByName ("homeEnbTxPowerDbm", doubleValue);
+ double homeEnbTxPowerDbm = doubleValue.Get ();
+ GlobalValue::GetValueByName ("macroEnbDlEarfcn", uintegerValue);
+ uint16_t macroEnbDlEarfcn = uintegerValue.Get ();
+ GlobalValue::GetValueByName ("homeEnbDlEarfcn", uintegerValue);
+ uint16_t homeEnbDlEarfcn = uintegerValue.Get ();
+ GlobalValue::GetValueByName ("macroEnbBandwidth", uintegerValue);
+ uint16_t macroEnbBandwidth = uintegerValue.Get ();
+ GlobalValue::GetValueByName ("homeEnbBandwidth", uintegerValue);
+ uint16_t homeEnbBandwidth = uintegerValue.Get ();
+ GlobalValue::GetValueByName ("simTime", doubleValue);
+ double simTime = doubleValue.Get ();
+ GlobalValue::GetValueByName ("epc", booleanValue);
+ bool epc = booleanValue.Get ();
+ GlobalValue::GetValueByName ("epcDl", booleanValue);
+ bool epcDl = booleanValue.Get ();
+ GlobalValue::GetValueByName ("epcUl", booleanValue);
+ bool epcUl = booleanValue.Get ();
+ GlobalValue::GetValueByName ("useUdp", booleanValue);
+ bool useUdp = booleanValue.Get ();
+ GlobalValue::GetValueByName ("generateRem", booleanValue);
+ bool generateRem = booleanValue.Get ();
+ GlobalValue::GetValueByName ("fadingTrace", stringValue);
+ std::string fadingTrace = stringValue.Get ();
Box macroUeBox;
@@ -359,10 +455,10 @@
lteHelper->SetPathlossModelAttribute ("Los2NlosThr", DoubleValue (1e6));
lteHelper->SetSpectrumChannelType ("ns3::MultiModelSpectrumChannel");
- if (!fadingFileTrace.empty ())
+ if (!fadingTrace.empty ())
{
lteHelper->SetAttribute ("FadingModel", StringValue ("ns3::TraceFadingLossModel"));
- lteHelper->SetFadingModelAttribute("TraceFilename", StringValue (fadingFileTrace));
+ lteHelper->SetFadingModelAttribute("TraceFilename", StringValue (fadingTrace));
}
Ptr<EpcHelper> epcHelper;
--- a/src/lte/helper/lte-helper.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/helper/lte-helper.cc Tue Jul 31 19:18:23 2012 +0200
@@ -308,11 +308,11 @@
Ptr<LteEnbPhy> phy = CreateObject<LteEnbPhy> (dlPhy, ulPhy);
- Ptr<LteCqiSinrChunkProcessor> p = Create<LteCqiSinrChunkProcessor> (phy->GetObject<LtePhy> ());
- ulPhy->AddSinrChunkProcessor (p);
+ Ptr<LteCtrlSinrChunkProcessor> pCtrl = Create<LteCtrlSinrChunkProcessor> (phy->GetObject<LtePhy> ());
+ ulPhy->AddCtrlSinrChunkProcessor (pCtrl); // for evaluating SRS UL-CQI
- Ptr<LtePemSinrChunkProcessor> pPem = Create<LtePemSinrChunkProcessor> (ulPhy);
- ulPhy->AddSinrChunkProcessor (pPem);
+ Ptr<LteDataSinrChunkProcessor> pData = Create<LteDataSinrChunkProcessor> (ulPhy, phy);
+ ulPhy->AddDataSinrChunkProcessor (pData); // for evaluating PUSCH UL-CQI
dlPhy->SetChannel (m_downlinkChannel);
ulPhy->SetChannel (m_uplinkChannel);
@@ -372,7 +372,8 @@
ulPhy->SetDevice (dev);
n->AddDevice (dev);
- ulPhy->SetGenericPhyRxEndOkCallback (MakeCallback (&LteEnbPhy::PhyPduReceived, phy));
+ ulPhy->SetLtePhyRxDataEndOkCallback (MakeCallback (&LteEnbPhy::PhyPduReceived, phy));
+ ulPhy->SetLtePhyRxCtrlEndOkCallback (MakeCallback (&LteEnbPhy::ReceiveLteControlMessageList, phy));
rrc->SetForwardUpCallback (MakeCallback (&LteEnbNetDevice::Receive, dev));
NS_LOG_LOGIC ("set the propagation model frequencies");
@@ -425,11 +426,11 @@
Ptr<LteUePhy> phy = CreateObject<LteUePhy> (dlPhy, ulPhy);
- Ptr<LteCqiSinrChunkProcessor> p = Create<LteCqiSinrChunkProcessor> (phy->GetObject<LtePhy> ());
- dlPhy->AddSinrChunkProcessor (p);
+ Ptr<LteCtrlSinrChunkProcessor> pCtrl = Create<LteCtrlSinrChunkProcessor> (phy->GetObject<LtePhy> (), dlPhy);
+ dlPhy->AddCtrlSinrChunkProcessor (pCtrl);
- Ptr<LtePemSinrChunkProcessor> pPem = Create<LtePemSinrChunkProcessor> (dlPhy);
- dlPhy->AddSinrChunkProcessor (pPem);
+ Ptr<LteDataSinrChunkProcessor> pData = Create<LteDataSinrChunkProcessor> (dlPhy);
+ dlPhy->AddDataSinrChunkProcessor (pData);
dlPhy->SetChannel (m_downlinkChannel);
ulPhy->SetChannel (m_uplinkChannel);
@@ -471,7 +472,8 @@
nas->SetDevice (dev);
n->AddDevice (dev);
- dlPhy->SetGenericPhyRxEndOkCallback (MakeCallback (&LteUePhy::PhyPduReceived, phy));
+ dlPhy->SetLtePhyRxDataEndOkCallback (MakeCallback (&LteUePhy::PhyPduReceived, phy));
+ dlPhy->SetLtePhyRxCtrlEndOkCallback (MakeCallback (&LteUePhy::ReceiveLteControlMessageList, phy));
nas->SetForwardUpCallback (MakeCallback (&LteUeNetDevice::Receive, dev));
@@ -495,11 +497,12 @@
LteHelper::Attach (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice)
{
NS_LOG_FUNCTION (this);
+ //enbRrc->SetCellId (enbDevice->GetObject<LteEnbNetDevice> ()->GetCellId ());
Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice> ();
Ptr<EpcUeNas> ueNas = ueLteDevice->GetNas ();
ueNas->Connect (enbDevice);
-
+
m_downlinkChannel->AddRx (ueLteDevice->GetPhy ()->GetDownlinkSpectrumPhy ());
// tricks needed for the simplified LTE-only simulations
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/ff-mac-common.cc Tue Jul 31 19:18:23 2012 +0200
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 CTTC
+ *
+ * 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: Marco Miozzo <mmiozzo@cttc.es>
+ */
+
+#include <ns3/ff-mac-common.h>
+
+namespace ns3 {
+
+
+VendorSpecificValue::~VendorSpecificValue ()
+{
+
+}
+
+
+} // namespace ns3
--- a/src/lte/model/ff-mac-common.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/ff-mac-common.h Tue Jul 31 19:18:23 2012 +0200
@@ -21,6 +21,11 @@
#ifndef FF_MAC_COMMON_H
#define FF_MAC_COMMON_H
+#include <ns3/simple-ref-count.h>
+#include <ns3/ptr.h>
+#include <vector>
+
+
/**
* Constants. See section 4.4
*/
@@ -49,6 +54,7 @@
#define MAX_SR_LIST 30
#define MAX_MAC_CE_LIST 30
+namespace ns3 {
enum Result_e
{
@@ -143,13 +149,22 @@
};
/**
+* \brief Base class for storing the values of vendor specific parameters
+*/
+struct VendorSpecificValue : public SimpleRefCount<VendorSpecificValue>
+{
+ virtual ~VendorSpecificValue ();
+
+};
+
+/**
* \brief See section 4.3.3 vendorSpecifiListElement
*/
struct VendorSpecificListElement_s
{
uint32_t m_type;
uint32_t m_length;
- void *m_value;
+ Ptr<VendorSpecificValue> m_value;
};
/**
@@ -464,5 +479,6 @@
uint8_t m_pagingSubframe;
};
+} // namespace ns3
#endif /* FF_MAC_COMMON_H */
--- a/src/lte/model/ff-mac-scheduler.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/ff-mac-scheduler.cc Tue Jul 31 19:18:23 2012 +0200
@@ -21,6 +21,8 @@
#include "ff-mac-scheduler.h"
#include <ns3/log.h>
+#include <ns3/enum.h>
+
NS_LOG_COMPONENT_DEFINE ("FfMacScheduler");
@@ -29,6 +31,13 @@
NS_OBJECT_ENSURE_REGISTERED (FfMacScheduler);
+FfMacScheduler::FfMacScheduler ()
+: m_ulCqiFilter (ALL_UL_CQI)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+
FfMacScheduler::~FfMacScheduler ()
{
NS_LOG_FUNCTION (this);
@@ -44,10 +53,19 @@
FfMacScheduler::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::FfMacScheduler")
- .SetParent<Object> ();
+ .SetParent<Object> ()
+ .AddAttribute ("UlCqiFilter",
+ "The filter to apply on UL CQIs received",
+ EnumValue (FfMacScheduler::ALL_UL_CQI),
+ MakeEnumAccessor (&FfMacScheduler::m_ulCqiFilter),
+ MakeEnumChecker (FfMacScheduler::SRS_UL_CQI, "SRS_UL_CQI",
+ FfMacScheduler::PUSCH_UL_CQI, "PUSCH_UL_CQI",
+ FfMacScheduler::ALL_UL_CQI, "ALL_UL_CQI"))
+ ;
return tid;
}
+
} // namespace ns3
--- a/src/lte/model/ff-mac-scheduler.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/ff-mac-scheduler.h Tue Jul 31 19:18:23 2012 +0200
@@ -45,6 +45,22 @@
{
public:
/**
+ * The type of UL CQI to be filtered (ALL means accept all the CQI,
+ * where a new CQI of any type overwrite the old one, even of another type)
+ *
+ */
+ enum UlCqiFilter_t
+ {
+ SRS_UL_CQI,
+ PUSCH_UL_CQI,
+ ALL_UL_CQI
+ };
+ /**
+ * constructor
+ *
+ */
+ FfMacScheduler ();
+ /**
* destructor
*
*/
@@ -83,6 +99,11 @@
*/
virtual FfMacSchedSapProvider* GetFfMacSchedSapProvider () = 0;
+
+protected:
+
+ UlCqiFilter_t m_ulCqiFilter;
+
};
} // namespace ns3
--- a/src/lte/model/ideal-control-messages.cc Sun Jul 29 14:29:41 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,208 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2010 TELEMATICS LAB, DEE - Politecnico di Bari
- *
- * 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: Giuseppe Piro <g.piro@poliba.it>
- * Marco Miozzo <marco.miozzo@cttc.es>
- */
-
-#include "ideal-control-messages.h"
-#include "ns3/address-utils.h"
-#include "ns3/uinteger.h"
-#include "ns3/log.h"
-#include "lte-net-device.h"
-#include "lte-ue-net-device.h"
-
-NS_LOG_COMPONENT_DEFINE ("IdealControlMessage");
-
-
-namespace ns3 {
-
-IdealControlMessage::IdealControlMessage (void)
- : m_source (0),
- m_destination (0)
-{
-}
-
-
-IdealControlMessage::~IdealControlMessage (void)
-{
- m_source = 0;
- m_destination = 0;
-}
-
-
-void
-IdealControlMessage::SetSourceDevice (Ptr<LteNetDevice> src)
-{
- m_source = src;
-}
-
-
-void
-IdealControlMessage::SetDestinationDevice (Ptr<LteNetDevice> dst)
-{
- m_destination = dst;
-}
-
-
-Ptr<LteNetDevice>
-IdealControlMessage::GetSourceDevice (void)
-{
- return m_source;
-}
-
-
-Ptr<LteNetDevice>
-IdealControlMessage::GetDestinationDevice (void)
-{
- return m_destination;
-}
-
-
-void
-IdealControlMessage::SetMessageType (IdealControlMessage::MessageType type)
-{
- m_type = type;
-}
-
-
-IdealControlMessage::MessageType
-IdealControlMessage::GetMessageType (void)
-{
- return m_type;
-}
-
-
-// ----------------------------------------------------------------------------------------------------------
-
-
-DlDciIdealControlMessage::DlDciIdealControlMessage (void)
-{
- SetMessageType (IdealControlMessage::DL_DCI);
-}
-
-
-DlDciIdealControlMessage::~DlDciIdealControlMessage (void)
-{
-
-}
-
-void
-DlDciIdealControlMessage::SetDci (DlDciListElement_s dci)
-{
- m_dci = dci;
-
-}
-
-
-DlDciListElement_s
-DlDciIdealControlMessage::GetDci (void)
-{
- return m_dci;
-}
-
-
-// ----------------------------------------------------------------------------------------------------------
-
-
-UlDciIdealControlMessage::UlDciIdealControlMessage (void)
-{
- SetMessageType (IdealControlMessage::UL_DCI);
-}
-
-
-UlDciIdealControlMessage::~UlDciIdealControlMessage (void)
-{
-
-}
-
-void
-UlDciIdealControlMessage::SetDci (UlDciListElement_s dci)
-{
- m_dci = dci;
-
-}
-
-
-UlDciListElement_s
-UlDciIdealControlMessage::GetDci (void)
-{
- return m_dci;
-}
-
-
-// ----------------------------------------------------------------------------------------------------------
-
-
-DlCqiIdealControlMessage::DlCqiIdealControlMessage (void)
-{
- SetMessageType (IdealControlMessage::DL_CQI);
-}
-
-
-DlCqiIdealControlMessage::~DlCqiIdealControlMessage (void)
-{
-
-}
-
-void
-DlCqiIdealControlMessage::SetDlCqi (CqiListElement_s dlcqi)
-{
- m_dlCqi = dlcqi;
-
-}
-
-
-CqiListElement_s
-DlCqiIdealControlMessage::GetDlCqi (void)
-{
- return m_dlCqi;
-}
-
-
-
-// ----------------------------------------------------------------------------------------------------------
-
-
-BsrIdealControlMessage::BsrIdealControlMessage (void)
-{
- SetMessageType (IdealControlMessage::BSR);
-}
-
-
-BsrIdealControlMessage::~BsrIdealControlMessage (void)
-{
-
-}
-
-void
-BsrIdealControlMessage::SetBsr (MacCeListElement_s bsr)
-{
- m_bsr = bsr;
-
-}
-
-
-MacCeListElement_s
-BsrIdealControlMessage::GetBsr (void)
-{
- return m_bsr;
-}
-
-
-} // namespace ns3
-
--- a/src/lte/model/ideal-control-messages.h Sun Jul 29 14:29:41 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,280 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2010 TELEMATICS LAB, DEE - Politecnico di Bari
- *
- * 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: Giuseppe Piro <g.piro@poliba.it>
- * Author: Marco Miozzo <marco.miozzo@cttc.es>
- */
-
-#ifndef IDEAL_CONTROL_MESSAGES_H
-#define IDEAL_CONTROL_MESSAGES_H
-
-#include "ns3/ptr.h"
-#include "ns3/simple-ref-count.h"
-#include <list>
-
-namespace ns3 {
-
-class LteNetDevice;
-
-
-/**
- * \ingroup lte
- *
- * The IdealControlMessage provides a basic implementations for
- * control messages (such as PDCCH allocation map, CQI feedbacks)
- * that are exchanged among eNodeB and UEs.
- */
-class IdealControlMessage : public SimpleRefCount<IdealControlMessage>
-{
-public:
- /**
- * The type of the message
- */
- enum MessageType
- {
- CQI_FEEDBACKS, ALLOCATION_MAP,
- DL_DCI, UL_DCI, // Downlink/Uplink Data Control Indicator
- DL_CQI, UL_CQI, // Downlink/Uplink Channel Quality Indicator
- BSR // Buffer Status Report
- };
-
- IdealControlMessage (void);
- virtual ~IdealControlMessage (void);
-
- /**
- * \brief Set the source device of the message
- * \param src the device that sends the message
- */
- void SetSourceDevice (Ptr<LteNetDevice> src);
- /**
- * \brief Set the destination device of the message
- * \param dst the device that receives the message
- */
- void SetDestinationDevice (Ptr<LteNetDevice> dst);
-
- /**
- * \brief Get the source device of the message
- * \return the pointer to the device that sends the message
- */
- Ptr<LteNetDevice> GetSourceDevice (void);
- /**
- * \brief Get the destination device of the message
- * \return the pointer to the device that receives the message
- */
- Ptr<LteNetDevice> GetDestinationDevice (void);
-
- /**
- * \brief Set the type of the message
- * \param type the type of the message
- */
- void SetMessageType (MessageType type);
- /**
- * \brief Get the type of the message
- * \return the type of the message
- */
- MessageType GetMessageType (void);
-
-private:
- Ptr<LteNetDevice> m_source;
- Ptr<LteNetDevice> m_destination;
- MessageType m_type;
-};
-} // namespace ns3
-
-#endif /* IDEAL_CONTROL_MESSAGES_H */
-
-
-
-
-// ----------------------------------------------------------------------------------------------------------
-
-
-#ifndef DL_DCI_IDEAL_CONTROL_MESSAGES_H
-#define DL_DCI_IDEAL_CONTROL_MESSAGES_H
-
-#include <ns3/object.h>
-#include <ns3/ff-mac-common.h>
-
-namespace ns3 {
-
-/**
- * \ingroup lte
- * The Downlink Data Control Indicator messages defines the RB allocation for the
- * users in the downlink
- */
-class DlDciIdealControlMessage : public IdealControlMessage
-{
-public:
- DlDciIdealControlMessage (void);
- virtual ~DlDciIdealControlMessage (void);
-
- /**
- * \brief add a DCI into the message
- * \param dci the dci
- */
- void SetDci (DlDciListElement_s dci);
-
- /**
- * \brief Get dic informations
- * \return dci messages
- */
- DlDciListElement_s GetDci (void);
-
-
-private:
- DlDciListElement_s m_dci;
-};
-} // namespace ns3
-
-#endif /* DL_DCI_IDEAL_CONTROL_MESSAGES_H */
-
-
-// ----------------------------------------------------------------------------------------------------------
-
-
-#ifndef UL_DCI_IDEAL_CONTROL_MESSAGES_H
-#define UL_DCI_IDEAL_CONTROL_MESSAGES_H
-
-#include <ns3/object.h>
-#include <ns3/ff-mac-common.h>
-
-namespace ns3 {
-
-/**
- * \ingroup lte
- * The Uplink Data Control Indicator messages defines the RB allocation for the
- * users in the uplink
- */
-class UlDciIdealControlMessage : public IdealControlMessage
-{
-public:
- UlDciIdealControlMessage (void);
- virtual ~UlDciIdealControlMessage (void);
-
- /**
- * \brief add a DCI into the message
- * \param dci the dci
- */
- void SetDci (UlDciListElement_s dci);
-
- /**
- * \brief Get dic informations
- * \return dci messages
- */
- UlDciListElement_s GetDci (void);
-
-
-private:
- UlDciListElement_s m_dci;
-};
-} // namespace ns3
-
-#endif /* UL_DCI_IDEAL_CONTROL_MESSAGES_H */
-
-
-
-// ----------------------------------------------------------------------------------------------------------
-
-
-
-#ifndef DLCQI_IDEAL_CONTROL_MESSAGES_H
-#define DLCQI_IDEAL_CONTROL_MESSAGES_H
-
-#include <ns3/object.h>
-#include <ns3/ff-mac-common.h>
-
-namespace ns3 {
-
-class LteNetDevice;
-
-/**
- * \ingroup lte
- * The downlink CqiIdealControlMessage defines an ideal list of
- * feedback about the channel quality sent by the UE to the eNodeB.
- */
-class DlCqiIdealControlMessage : public IdealControlMessage
-{
-public:
- DlCqiIdealControlMessage (void);
- virtual ~DlCqiIdealControlMessage (void);
-
- /**
- * \brief add a DL-CQI feedback record into the message.
- * \param dlcqi the DL cqi feedback
- */
- void SetDlCqi (CqiListElement_s dlcqi);
-
- /**
- * \brief Get DL cqi informations
- * \return dlcqi messages
- */
- CqiListElement_s GetDlCqi (void);
-
-
-private:
- CqiListElement_s m_dlCqi;
-};
-} // namespace ns3
-
-#endif /* DLCQI_IDEAL_CONTROL_MESSAGES_H */
-
-
-// ----------------------------------------------------------------------------------------------------------
-
-#ifndef BSR_IDEAL_CONTROL_MESSAGES_H
-#define BSR_IDEAL_CONTROL_MESSAGES_H
-
-#include <ns3/object.h>
-#include <ns3/ff-mac-common.h>
-
-namespace ns3 {
-
-class LteNetDevice;
-
-/**
- * \ingroup lte
- * The uplink BsrIdealControlMessage defines the specific
- * extension of the CE element for reporting the buffer status report
- */
-class BsrIdealControlMessage : public IdealControlMessage
-{
-public:
- BsrIdealControlMessage (void);
- virtual ~BsrIdealControlMessage (void);
-
- /**
- * \brief add a BSR feedback record into the message.
- * \param bsr the BSR feedback
- */
- void SetBsr (MacCeListElement_s ulcqi);
-
- /**
- * \brief Get BSR informations
- * \return BSR message
- */
- MacCeListElement_s GetBsr (void);
-
-
-private:
- MacCeListElement_s m_bsr;
-
-
-};
-} // namespace ns3
-
-#endif /* BSR_IDEAL_CONTROL_MESSAGES_H */
-
--- a/src/lte/model/lte-common.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-common.h Tue Jul 31 19:18:23 2012 +0200
@@ -56,10 +56,24 @@
friend bool operator < (const ImsiLcidPair_t &a, const ImsiLcidPair_t &b);
};
+/**
+* \brief Parameters for configuring the UE
+*/
struct LteUeConfig_t
{
uint16_t m_rnti;
+ /**
+ * When false means that the message is inteded foro configuring a new UE
+ */
+ bool m_reconfigureFlag;
+ /**
+ * Transmission mode [1..7] (i.e., SISO, MIMO, etc.)
+ */
uint8_t m_transmissionMode;
+ /**
+ * Srs Configuration index for UE specific SRS, see section 8.2 of TS 36.213
+ */
+ uint16_t m_srsConfigurationIndex;
public:
LteUeConfig_t ();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-control-messages.cc Tue Jul 31 19:18:23 2012 +0200
@@ -0,0 +1,180 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 TELEMATICS LAB, DEE - Politecnico di Bari
+ *
+ * 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: Giuseppe Piro <g.piro@poliba.it>
+ * Marco Miozzo <marco.miozzo@cttc.es>
+ */
+
+#include "lte-control-messages.h"
+#include "ns3/address-utils.h"
+#include "ns3/uinteger.h"
+#include "ns3/log.h"
+#include "lte-net-device.h"
+#include "lte-ue-net-device.h"
+
+NS_LOG_COMPONENT_DEFINE ("LteControlMessage");
+
+
+namespace ns3 {
+
+LteControlMessage::LteControlMessage (void)
+ : m_source (0),
+ m_destination (0)
+{
+}
+
+
+LteControlMessage::~LteControlMessage (void)
+{
+ m_source = 0;
+ m_destination = 0;
+}
+
+
+void
+LteControlMessage::SetMessageType (LteControlMessage::MessageType type)
+{
+ m_type = type;
+}
+
+
+LteControlMessage::MessageType
+LteControlMessage::GetMessageType (void)
+{
+ return m_type;
+}
+
+
+// ----------------------------------------------------------------------------------------------------------
+
+
+DlDciLteControlMessage::DlDciLteControlMessage (void)
+{
+ SetMessageType (LteControlMessage::DL_DCI);
+}
+
+
+DlDciLteControlMessage::~DlDciLteControlMessage (void)
+{
+
+}
+
+void
+DlDciLteControlMessage::SetDci (DlDciListElement_s dci)
+{
+ m_dci = dci;
+
+}
+
+
+DlDciListElement_s
+DlDciLteControlMessage::GetDci (void)
+{
+ return m_dci;
+}
+
+
+// ----------------------------------------------------------------------------------------------------------
+
+
+UlDciLteControlMessage::UlDciLteControlMessage (void)
+{
+ SetMessageType (LteControlMessage::UL_DCI);
+}
+
+
+UlDciLteControlMessage::~UlDciLteControlMessage (void)
+{
+
+}
+
+void
+UlDciLteControlMessage::SetDci (UlDciListElement_s dci)
+{
+ m_dci = dci;
+
+}
+
+
+UlDciListElement_s
+UlDciLteControlMessage::GetDci (void)
+{
+ return m_dci;
+}
+
+
+// ----------------------------------------------------------------------------------------------------------
+
+
+DlCqiLteControlMessage::DlCqiLteControlMessage (void)
+{
+ SetMessageType (LteControlMessage::DL_CQI);
+}
+
+
+DlCqiLteControlMessage::~DlCqiLteControlMessage (void)
+{
+
+}
+
+void
+DlCqiLteControlMessage::SetDlCqi (CqiListElement_s dlcqi)
+{
+ m_dlCqi = dlcqi;
+
+}
+
+
+CqiListElement_s
+DlCqiLteControlMessage::GetDlCqi (void)
+{
+ return m_dlCqi;
+}
+
+
+
+// ----------------------------------------------------------------------------------------------------------
+
+
+BsrLteControlMessage::BsrLteControlMessage (void)
+{
+ SetMessageType (LteControlMessage::BSR);
+}
+
+
+BsrLteControlMessage::~BsrLteControlMessage (void)
+{
+
+}
+
+void
+BsrLteControlMessage::SetBsr (MacCeListElement_s bsr)
+{
+ m_bsr = bsr;
+
+}
+
+
+MacCeListElement_s
+BsrLteControlMessage::GetBsr (void)
+{
+ return m_bsr;
+}
+
+
+} // namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-control-messages.h Tue Jul 31 19:18:23 2012 +0200
@@ -0,0 +1,257 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 TELEMATICS LAB, DEE - Politecnico di Bari
+ *
+ * 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: Giuseppe Piro <g.piro@poliba.it>
+ * Author: Marco Miozzo <marco.miozzo@cttc.es>
+ */
+
+#ifndef LTE_CONTROL_MESSAGES_H
+#define LTE_CONTROL_MESSAGES_H
+
+#include "ns3/ptr.h"
+#include "ns3/simple-ref-count.h"
+#include <list>
+
+namespace ns3 {
+
+class LteNetDevice;
+
+
+/**
+ * \ingroup lte
+ *
+ * The LteControlMessage provides a basic implementations for
+ * control messages (such as PDCCH allocation map, CQI feedbacks)
+ * that are exchanged among eNodeB and UEs.
+ */
+class LteControlMessage : public SimpleRefCount<LteControlMessage>
+{
+public:
+ /**
+ * The type of the message
+ */
+ enum MessageType
+ {
+ DL_DCI, UL_DCI, // Downlink/Uplink Data Control Indicator
+ DL_CQI, UL_CQI, // Downlink/Uplink Channel Quality Indicator
+ BSR // Buffer Status Report
+ };
+
+ LteControlMessage (void);
+ virtual ~LteControlMessage (void);
+
+ /**
+ * \brief Set the type of the message
+ * \param type the type of the message
+ */
+ void SetMessageType (MessageType type);
+ /**
+ * \brief Get the type of the message
+ * \return the type of the message
+ */
+ MessageType GetMessageType (void);
+
+private:
+ Ptr<LteNetDevice> m_source;
+ Ptr<LteNetDevice> m_destination;
+ MessageType m_type;
+};
+} // namespace ns3
+
+#endif /* LTE_CONTROL_MESSAGES_H */
+
+
+
+
+// ----------------------------------------------------------------------------------------------------------
+
+
+#ifndef DL_DCI_LTE_CONTROL_MESSAGES_H
+#define DL_DCI_LTE_CONTROL_MESSAGES_H
+
+#include <ns3/object.h>
+#include <ns3/ff-mac-common.h>
+
+namespace ns3 {
+
+/**
+ * \ingroup lte
+ * The Downlink Data Control Indicator messages defines the RB allocation for the
+ * users in the downlink
+ */
+class DlDciLteControlMessage : public LteControlMessage
+{
+public:
+ DlDciLteControlMessage (void);
+ virtual ~DlDciLteControlMessage (void);
+
+ /**
+ * \brief add a DCI into the message
+ * \param dci the dci
+ */
+ void SetDci (DlDciListElement_s dci);
+
+ /**
+ * \brief Get dic informations
+ * \return dci messages
+ */
+ DlDciListElement_s GetDci (void);
+
+
+private:
+ DlDciListElement_s m_dci;
+};
+} // namespace ns3
+
+#endif /* DL_DCI_LTE_CONTROL_MESSAGES_H */
+
+
+// ----------------------------------------------------------------------------------------------------------
+
+
+#ifndef UL_DCI_LTE_CONTROL_MESSAGES_H
+#define UL_DCI_LTE_CONTROL_MESSAGES_H
+
+#include <ns3/object.h>
+#include <ns3/ff-mac-common.h>
+
+namespace ns3 {
+
+/**
+ * \ingroup lte
+ * The Uplink Data Control Indicator messages defines the RB allocation for the
+ * users in the uplink
+ */
+class UlDciLteControlMessage : public LteControlMessage
+{
+public:
+ UlDciLteControlMessage (void);
+ virtual ~UlDciLteControlMessage (void);
+
+ /**
+ * \brief add a DCI into the message
+ * \param dci the dci
+ */
+ void SetDci (UlDciListElement_s dci);
+
+ /**
+ * \brief Get dic informations
+ * \return dci messages
+ */
+ UlDciListElement_s GetDci (void);
+
+
+private:
+ UlDciListElement_s m_dci;
+};
+} // namespace ns3
+
+#endif /* UL_DCI_LTE_CONTROL_MESSAGES_H */
+
+
+
+// ----------------------------------------------------------------------------------------------------------
+
+
+
+#ifndef DLCQI_LTE_CONTROL_MESSAGES_H
+#define DLCQI_LTE_CONTROL_MESSAGES_H
+
+#include <ns3/object.h>
+#include <ns3/ff-mac-common.h>
+
+namespace ns3 {
+
+class LteNetDevice;
+
+/**
+ * \ingroup lte
+ * The downlink CqiLteControlMessage defines an ideal list of
+ * feedback about the channel quality sent by the UE to the eNodeB.
+ */
+class DlCqiLteControlMessage : public LteControlMessage
+{
+public:
+ DlCqiLteControlMessage (void);
+ virtual ~DlCqiLteControlMessage (void);
+
+ /**
+ * \brief add a DL-CQI feedback record into the message.
+ * \param dlcqi the DL cqi feedback
+ */
+ void SetDlCqi (CqiListElement_s dlcqi);
+
+ /**
+ * \brief Get DL cqi informations
+ * \return dlcqi messages
+ */
+ CqiListElement_s GetDlCqi (void);
+
+
+private:
+ CqiListElement_s m_dlCqi;
+};
+} // namespace ns3
+
+#endif /* DLCQI_LTE_CONTROL_MESSAGES_H */
+
+
+// ----------------------------------------------------------------------------------------------------------
+
+#ifndef BSR_LTE_CONTROL_MESSAGES_H
+#define BSR_LTE_CONTROL_MESSAGES_H
+
+#include <ns3/object.h>
+#include <ns3/ff-mac-common.h>
+
+namespace ns3 {
+
+class LteNetDevice;
+
+/**
+ * \ingroup lte
+ * The uplink BsrLteControlMessage defines the specific
+ * extension of the CE element for reporting the buffer status report
+ */
+class BsrLteControlMessage : public LteControlMessage
+{
+public:
+ BsrLteControlMessage (void);
+ virtual ~BsrLteControlMessage (void);
+
+ /**
+ * \brief add a BSR feedback record into the message.
+ * \param bsr the BSR feedback
+ */
+ void SetBsr (MacCeListElement_s ulcqi);
+
+ /**
+ * \brief Get BSR informations
+ * \return BSR message
+ */
+ MacCeListElement_s GetBsr (void);
+
+
+private:
+ MacCeListElement_s m_bsr;
+
+
+};
+} // namespace ns3
+
+#endif /* LTE_CONTROL_MESSAGES_H */
+
--- a/src/lte/model/lte-enb-cmac-sap.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-enb-cmac-sap.h Tue Jul 31 19:18:23 2012 +0200
@@ -26,7 +26,6 @@
#include <ns3/ff-mac-common.h>
#include <ns3/eps-bearer.h>
#include <ns3/lte-common.h>
-#include <ns3/ff-mac-csched-sap.h>
namespace ns3 {
@@ -104,7 +103,22 @@
*/
virtual void ReleaseLc (uint16_t rnti, uint8_t lcid) = 0;
- virtual void RrcUpdateConfigurationReq (FfMacCschedSapProvider::CschedUeConfigReqParameters params) = 0;
+ /**
+ * \brief Parameters for [re]configuring the UE
+ */
+ struct UeConfig
+ {
+ /**
+ * UE id within this cell
+ */
+ uint16_t m_rnti;
+ /**
+ * Transmission mode [1..7] (i.e., SISO, MIMO, etc.)
+ */
+ uint8_t m_transmissionMode;
+ };
+
+ virtual void UeUpdateConfigurationReq (UeConfig params) = 0;
};
@@ -129,7 +143,28 @@
* \param success true if the operation was successful, false otherwise
*/
virtual void NotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success) = 0;
- virtual void RrcConfigurationUpdateInd (LteUeConfig_t params) = 0;
+
+ /**
+ * \brief Parameters for [re]configuring the UE
+ */
+ struct UeConfig
+ {
+ /**
+ * UE id within this cell
+ */
+ uint16_t m_rnti;
+ /**
+ * Transmission mode [1..7] (i.e., SISO, MIMO, etc.)
+ */
+ uint8_t m_transmissionMode;
+ };
+
+ /**
+ * Notify the RRC of a UE config updated requested by the MAC (normally, by the scheduler)
+ *
+ * \param params
+ */
+ virtual void RrcConfigurationUpdateInd (UeConfig params) = 0;
};
--- a/src/lte/model/lte-enb-cphy-sap.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-enb-cphy-sap.h Tue Jul 31 19:18:23 2012 +0200
@@ -62,22 +62,26 @@
* \param dlEarfcn the DL EARFCN
*/
virtual void SetEarfcn (uint16_t ulEarfcn, uint16_t dlEarfcn) = 0;
-
-
+
/**
* Add a new UE to the cell
*
* \param rnti the UE id relative to this cell
*/
virtual void AddUe (uint16_t rnti) = 0;
-
/**
- * \param rnti the RNTI of the user
- * \param txMode the transmissionMode of the user
- */
+ * \param rnti the RNTI of the user
+ * \param txMode the transmissionMode of the user
+ */
virtual void SetTransmissionMode (uint16_t rnti, uint8_t txMode) = 0;
+ /**
+ * \param rnti the RNTI of the user
+ * \param txMode the SRS Configuration Index of the user
+ */
+ virtual void SetSrsConfigurationIndex (uint16_t rnti, uint16_t srsCi) = 0;
+
};
@@ -116,6 +120,7 @@
virtual void SetEarfcn (uint16_t ulEarfcn, uint16_t dlEarfcn);
virtual void AddUe (uint16_t rnti);
virtual void SetTransmissionMode (uint16_t rnti, uint8_t txMode);
+ virtual void SetSrsConfigurationIndex (uint16_t rnti, uint16_t srsCi);
private:
MemberLteEnbCphySapProvider ();
@@ -170,6 +175,13 @@
m_owner->DoSetTransmissionMode (rnti, txMode);
}
+template <class C>
+void
+MemberLteEnbCphySapProvider<C>::SetSrsConfigurationIndex (uint16_t rnti, uint16_t srsCi)
+{
+ m_owner->DoSetSrsConfigurationIndex (rnti, srsCi);
+}
+
--- a/src/lte/model/lte-enb-mac.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-enb-mac.cc Tue Jul 31 19:18:23 2012 +0200
@@ -25,7 +25,7 @@
#include <ns3/packet.h>
#include "lte-amc.h"
-#include "ideal-control-messages.h"
+#include "lte-control-messages.h"
#include "lte-enb-net-device.h"
#include "lte-ue-net-device.h"
@@ -63,7 +63,7 @@
virtual void AddLc (LcInfo lcinfo, LteMacSapUser* msu);
virtual void ReconfigureLc (LcInfo lcinfo);
virtual void ReleaseLc (uint16_t rnti, uint8_t lcid);
- virtual void RrcUpdateConfigurationReq (FfMacCschedSapProvider::CschedUeConfigReqParameters params);
+ virtual void UeUpdateConfigurationReq (UeConfig params);
private:
LteEnbMac* m_mac;
@@ -112,9 +112,9 @@
}
void
-EnbMacMemberLteEnbCmacSapProvider::RrcUpdateConfigurationReq (FfMacCschedSapProvider::CschedUeConfigReqParameters params)
+EnbMacMemberLteEnbCmacSapProvider::UeUpdateConfigurationReq (UeConfig params)
{
- m_mac->DoRrcUpdateConfigurationReq (params);
+ m_mac->DoUeUpdateConfigurationReq (params);
}
@@ -232,8 +232,8 @@
// inherited from LteEnbPhySapUser
virtual void ReceivePhyPdu (Ptr<Packet> p);
virtual void SubframeIndication (uint32_t frameNo, uint32_t subframeNo);
- virtual void ReceiveIdealControlMessage (Ptr<IdealControlMessage> msg);
- virtual void UlCqiReport (UlCqi_s ulcqi);
+ virtual void ReceiveLteControlMessage (Ptr<LteControlMessage> msg);
+ virtual void UlCqiReport (FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi);
private:
LteEnbMac* m_mac;
@@ -257,13 +257,13 @@
}
void
-EnbMacMemberLteEnbPhySapUser::ReceiveIdealControlMessage (Ptr<IdealControlMessage> msg)
+EnbMacMemberLteEnbPhySapUser::ReceiveLteControlMessage (Ptr<LteControlMessage> msg)
{
- m_mac->DoReceiveIdealControlMessage (msg);
+ m_mac->DoReceiveLteControlMessage (msg);
}
void
-EnbMacMemberLteEnbPhySapUser::UlCqiReport (UlCqi_s ulcqi)
+EnbMacMemberLteEnbPhySapUser::UlCqiReport (FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi)
{
m_mac->DoUlCqiReport (ulcqi);
}
@@ -414,8 +414,6 @@
// Get downlink transmission opportunities
-// uint32_t dlSchedFrameNo = (0x3FF & (m_frameNo >> 4));
-// uint32_t dlSchedSubframeNo = (0xF & m_subframeNo);
uint32_t dlSchedFrameNo = m_frameNo;
uint32_t dlSchedSubframeNo = m_subframeNo;
// NS_LOG_DEBUG (this << " sfn " << frameNo << " sbfn " << subframeNo);
@@ -435,32 +433,20 @@
// --- UPLINK ---
// Send UL-CQI info to the scheduler
- if (m_ulCqiReceived.size () > 0)
+ std::vector <FfMacSchedSapProvider::SchedUlCqiInfoReqParameters>::iterator itCqi;
+ for (uint16_t i = 0; i < m_ulCqiReceived.size (); i++)
{
- FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqiInfoReq;
if (subframeNo>1)
{
- ulcqiInfoReq.m_sfnSf = ((0x3FF & frameNo) << 4) | (0xF & subframeNo);
+ m_ulCqiReceived.at (i).m_sfnSf = ((0x3FF & frameNo) << 4) | (0xF & subframeNo);
}
else
{
- ulcqiInfoReq.m_sfnSf = ((0x3FF & (frameNo-1)) << 4) | (0xF & 10);
+ m_ulCqiReceived.at (i).m_sfnSf = ((0x3FF & (frameNo-1)) << 4) | (0xF & 10);
}
- int cqiNum = m_ulCqiReceived.size ();
- if (cqiNum >= 1)
- {
- ulcqiInfoReq.m_ulCqi = m_ulCqiReceived.at (cqiNum - 1);
- if (cqiNum > 1)
- {
- // empty old ul cqi
- while (m_ulCqiReceived.size () > 0)
- {
- m_ulCqiReceived.pop_back ();
- }
- }
- m_schedSapProvider->SchedUlCqiInfoReq (ulcqiInfoReq);
- }
+ m_schedSapProvider->SchedUlCqiInfoReq (m_ulCqiReceived.at (i));
}
+ m_ulCqiReceived.clear ();
// Send BSR reports to the scheduler
if (m_ulCeReceived.size () > 0)
@@ -484,7 +470,6 @@
}
else
{
-// ulSchedSubframeNo = (ulSchedSubframeNo + (2*m_macChTtiDelay)) % 11;
ulSchedSubframeNo = ulSchedSubframeNo + (m_macChTtiDelay+UL_PUSCH_TTIS_DELAY);
}
FfMacSchedSapProvider::SchedUlTriggerReqParameters ulparams;
@@ -501,7 +486,6 @@
// reset UL info
- //std::map <uint16_t,UlInfoListElement_s>::iterator it;
for (it = m_ulInfoListElements.begin (); it != m_ulInfoListElements.end (); it++)
{
for (uint16_t i = 0; i < (*it).second.m_ulReception.size (); i++)
@@ -514,30 +498,30 @@
}
void
-LteEnbMac::DoReceiveIdealControlMessage (Ptr<IdealControlMessage> msg)
+LteEnbMac::DoReceiveLteControlMessage (Ptr<LteControlMessage> msg)
{
NS_LOG_FUNCTION (this << msg);
- if (msg->GetMessageType () == IdealControlMessage::DL_CQI)
+ if (msg->GetMessageType () == LteControlMessage::DL_CQI)
{
- Ptr<DlCqiIdealControlMessage> dlcqi = DynamicCast<DlCqiIdealControlMessage> (msg);
- ReceiveDlCqiIdealControlMessage (dlcqi);
+ Ptr<DlCqiLteControlMessage> dlcqi = DynamicCast<DlCqiLteControlMessage> (msg);
+ ReceiveDlCqiLteControlMessage (dlcqi);
}
- else if (msg->GetMessageType () == IdealControlMessage::BSR)
+ else if (msg->GetMessageType () == LteControlMessage::BSR)
{
- Ptr<BsrIdealControlMessage> bsr = DynamicCast<BsrIdealControlMessage> (msg);
+ Ptr<BsrLteControlMessage> bsr = DynamicCast<BsrLteControlMessage> (msg);
ReceiveBsrMessage (bsr->GetBsr ());
}
else
{
- NS_LOG_LOGIC (this << " IdealControlMessage not recognized");
+ NS_LOG_LOGIC (this << " LteControlMessage not recognized");
}
}
void
-LteEnbMac::DoUlCqiReport (UlCqi_s ulcqi)
+LteEnbMac::DoUlCqiReport (FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi)
{
- if (ulcqi.m_type == UlCqi_s::PUSCH)
+ if (ulcqi.m_ulCqi.m_type == UlCqi_s::PUSCH)
{
NS_LOG_DEBUG (this << " eNB rxed an PUSCH UL-CQI");
}
@@ -547,7 +531,7 @@
void
-LteEnbMac::ReceiveDlCqiIdealControlMessage (Ptr<DlCqiIdealControlMessage> msg)
+LteEnbMac::ReceiveDlCqiLteControlMessage (Ptr<DlCqiLteControlMessage> msg)
{
NS_LOG_FUNCTION (this << msg);
@@ -771,9 +755,9 @@
}
}
// send the relative DCI
- Ptr<DlDciIdealControlMessage> msg = Create<DlDciIdealControlMessage> ();
+ Ptr<DlDciLteControlMessage> msg = Create<DlDciLteControlMessage> ();
msg->SetDci (ind.m_buildDataList.at (i).m_dci);
- m_enbPhySapProvider->SendIdealControlMessage (msg);
+ m_enbPhySapProvider->SendLteControlMessage (msg);
}
// Fire the trace with the DL information
@@ -815,9 +799,9 @@
for (unsigned int i = 0; i < ind.m_dciList.size (); i++)
{
// send the correspondent ul dci
- Ptr<UlDciIdealControlMessage> msg = Create<UlDciIdealControlMessage> ();
+ Ptr<UlDciLteControlMessage> msg = Create<UlDciLteControlMessage> ();
msg->SetDci (ind.m_dciList.at (i));
- m_enbPhySapProvider->SendIdealControlMessage (msg);
+ m_enbPhySapProvider->SendLteControlMessage (msg);
}
// Fire the trace with the UL information
@@ -876,16 +860,17 @@
{
NS_LOG_FUNCTION (this);
// propagates to RRC
- LteUeConfig_t ueConfigUpdate;
+ LteEnbCmacSapUser::UeConfig ueConfigUpdate;
ueConfigUpdate.m_rnti = params.m_rnti;
ueConfigUpdate.m_transmissionMode = params.m_transmissionMode;
m_cmacSapUser->RrcConfigurationUpdateInd (ueConfigUpdate);
}
void
-LteEnbMac::DoRrcUpdateConfigurationReq (FfMacCschedSapProvider::CschedUeConfigReqParameters params)
+LteEnbMac::DoUeUpdateConfigurationReq (LteEnbCmacSapProvider::UeConfig params)
{
NS_LOG_FUNCTION (this);
+
// propagates to scheduler
FfMacCschedSapProvider::CschedUeConfigReqParameters req;
req.m_rnti = params.m_rnti;
--- a/src/lte/model/lte-enb-mac.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-enb-mac.h Tue Jul 31 19:18:23 2012 +0200
@@ -36,9 +36,9 @@
namespace ns3 {
-class DlCqiIdealControlMessage;
-class UlCqiIdealControlMessage;
-class PdcchMapIdealControlMessage;
+class DlCqiLteControlMessage;
+class UlCqiLteControlMessage;
+class PdcchMapLteControlMessage;
@@ -123,9 +123,9 @@
* \brief Receive a DL CQI ideal control message
* \param msg the DL CQI message
*/
- void ReceiveDlCqiIdealControlMessage (Ptr<DlCqiIdealControlMessage> msg);
+ void ReceiveDlCqiLteControlMessage (Ptr<DlCqiLteControlMessage> msg);
- void DoReceiveIdealControlMessage (Ptr<IdealControlMessage> msg);
+ void DoReceiveLteControlMessage (Ptr<LteControlMessage> msg);
/**
* \brief Receive a CE element containing the buffer status report
@@ -133,7 +133,7 @@
*/
void ReceiveBsrMessage (MacCeListElement_s bsr);
- void DoUlCqiReport (UlCqi_s ulcqi);
+ void DoUlCqiReport (FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi);
@@ -164,7 +164,7 @@
void DoSchedDlConfigInd (FfMacSchedSapUser::SchedDlConfigIndParameters ind);
void DoSchedUlConfigInd (FfMacSchedSapUser::SchedUlConfigIndParameters params);
- void DoRrcUpdateConfigurationReq (FfMacCschedSapProvider::CschedUeConfigReqParameters params);
+ void DoUeUpdateConfigurationReq (LteEnbCmacSapProvider::UeConfig params);
/**
* \brief Forwarded from LteEnbPhySapUser: trigger the start from a new frame
@@ -185,11 +185,10 @@
private:
private:
- // std::map <uint16_t, std::map <uint8_t,Ptr<LteMacSapUser> > > m_rlcAttached;
std::map <LteFlowId_t, LteMacSapUser*> m_rlcAttached;
std::vector <CqiListElement_s> m_dlCqiReceived; // DL-CQI received
- std::vector <UlCqi_s> m_ulCqiReceived; // UL-CQI received
+ std::vector <FfMacSchedSapProvider::SchedUlCqiInfoReqParameters> m_ulCqiReceived; // UL-CQI received
std::vector <MacCeListElement_s> m_ulCeReceived; // CE received (BSR up to now)
--- a/src/lte/model/lte-enb-net-device.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-enb-net-device.cc Tue Jul 31 19:18:23 2012 +0200
@@ -277,6 +277,7 @@
NS_LOG_FUNCTION (this);
m_rrc->ConfigureCell (m_ulBandwidth, m_dlBandwidth, m_ulEarfcn, m_dlEarfcn, m_cellId);
+ m_rrc->SetCellId (m_cellId);
}
--- a/src/lte/model/lte-enb-phy-sap.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-enb-phy-sap.h Tue Jul 31 19:18:23 2012 +0200
@@ -25,10 +25,11 @@
#include <ns3/packet.h>
#include <ns3/ff-mac-common.h>
+#include <ns3/ff-mac-sched-sap.h>
namespace ns3 {
-class IdealControlMessage;
+class LteControlMessage;
/**
* Service Access Point (SAP) offered by the eNB-PHY to the eNB-MAC
@@ -48,11 +49,11 @@
*/
virtual void SendMacPdu (Ptr<Packet> p) = 0;
- /**
- * \brief Send SendIdealControlMessage (PDCCH map, CQI feedbacks) using the ideal control channel
+ /**
+ * \brief Send SendLteControlMessage (PDCCH map, CQI feedbacks) using the ideal control channel
* \param msg the Ideal Control Message to send
*/
- virtual void SendIdealControlMessage (Ptr<IdealControlMessage> msg) = 0;
+ virtual void SendLteControlMessage (Ptr<LteControlMessage> msg) = 0;
/**
* \brief Get the delay from MAC to Channel expressed in TTIs
@@ -91,16 +92,16 @@
virtual void SubframeIndication (uint32_t frameNo, uint32_t subframeNo) = 0;
/**
- * \brief Receive SendIdealControlMessage (PDCCH map, CQI feedbacks) using the ideal control channel
+ * \brief Receive SendLteControlMessage (PDCCH map, CQI feedbacks) using the ideal control channel
* \param msg the Ideal Control Message to receive
*/
- virtual void ReceiveIdealControlMessage (Ptr<IdealControlMessage> msg) = 0;
+ virtual void ReceiveLteControlMessage (Ptr<LteControlMessage> msg) = 0;
/**
* \brief Returns to MAC level the UL-CQI evaluated
* \param ulcqi the UL-CQI (see FF MAC API 4.3.29)
*/
- virtual void UlCqiReport (UlCqi_s ulcqi) = 0;
+ virtual void UlCqiReport (FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi) = 0;
};
--- a/src/lte/model/lte-enb-phy.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-enb-phy.cc Tue Jul 31 19:18:23 2012 +0200
@@ -31,11 +31,12 @@
#include "lte-ue-phy.h"
#include "lte-net-device.h"
#include "lte-spectrum-value-helper.h"
-#include "ideal-control-messages.h"
+#include "lte-control-messages.h"
#include "lte-enb-net-device.h"
#include "lte-ue-rrc.h"
#include "lte-enb-mac.h"
#include <ns3/lte-common.h>
+#include <ns3/lte-vendor-specific-parameters.h>
// WILD HACK for the inizialization of direct eNB-UE ctrl messaging
#include <ns3/node-list.h>
@@ -47,6 +48,14 @@
namespace ns3 {
+// duration of the data part of a subframe in DL
+// = 0.001 / 14 * 11 (fixed to 11 symbols) -1ns as margin to avoid overlapping simulator events
+static const Time DL_DATA_DURATION = NanoSeconds (785714 -1);
+
+// delay from subframe start to transmission of the data in DL
+// = 0.001 / 14 * 3 (ctrl fixed to 3 symbols)
+static const Time DL_CTRL_DELAY_FROM_SUBFRAME_START = NanoSeconds (214286);
+
////////////////////////////////////////
// member SAP forwarders
////////////////////////////////////////
@@ -61,9 +70,10 @@
virtual void SendMacPdu (Ptr<Packet> p);
virtual void SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth);
virtual void SetCellId (uint16_t cellId);
- virtual void SendIdealControlMessage (Ptr<IdealControlMessage> msg);
+ virtual void SendLteControlMessage (Ptr<LteControlMessage> msg);
virtual uint8_t GetMacChTtiDelay ();
virtual void SetTransmissionMode (uint16_t rnti, uint8_t txMode);
+ virtual void SetSrsConfigurationIndex (uint16_t rnti, uint16_t srcCi);
private:
@@ -95,9 +105,9 @@
}
void
-EnbMemberLteEnbPhySapProvider::SendIdealControlMessage (Ptr<IdealControlMessage> msg)
+EnbMemberLteEnbPhySapProvider::SendLteControlMessage (Ptr<LteControlMessage> msg)
{
- m_phy->DoSendIdealControlMessage (msg);
+ m_phy->DoSendLteControlMessage (msg);
}
uint8_t
@@ -112,6 +122,12 @@
m_phy->DoSetTransmissionMode (rnti, txMode);
}
+void
+EnbMemberLteEnbPhySapProvider::SetSrsConfigurationIndex (uint16_t rnti, uint16_t srcCi)
+{
+ m_phy->DoSetSrsConfigurationIndex (rnti, srcCi);
+}
+
////////////////////////////////////////
// generic LteEnbPhy methods
@@ -133,7 +149,9 @@
m_enbPhySapUser (0),
m_enbCphySapUser (0),
m_nrFrames (0),
- m_nrSubFrames (0)
+ m_nrSubFrames (0),
+ m_srsPeriodicity (0),
+ m_currentSrsOffset (0)
{
m_enbPhySapProvider = new EnbMemberLteEnbPhySapProvider (this);
m_enbCphySapProvider = new MemberLteEnbCphySapProvider<LteEnbPhy> (this);
@@ -184,6 +202,7 @@
{
NS_LOG_FUNCTION (this);
m_ueAttached.clear ();
+ m_srsUeOffset.clear ();
delete m_enbPhySapProvider;
delete m_enbCphySapProvider;
LtePhy::DoDispose ();
@@ -262,14 +281,14 @@
{
Ptr<PacketBurst> pb = CreateObject <PacketBurst> ();
m_packetBurstQueue.push_back (pb);
- std::list<Ptr<IdealControlMessage> > l;
+ std::list<Ptr<LteControlMessage> > l;
m_controlMessagesQueue.push_back (l);
- std::list<UlDciIdealControlMessage> l1;
+ std::list<UlDciLteControlMessage> l1;
m_ulDciQueue.push_back (l1);
}
for (int i = 0; i < UL_PUSCH_TTIS_DELAY; i++)
{
- std::list<UlDciIdealControlMessage> l1;
+ std::list<UlDciLteControlMessage> l1;
m_ulDciQueue.push_back (l1);
}
}
@@ -283,14 +302,14 @@
bool
-LteEnbPhy::AddUePhy (uint16_t rnti, Ptr<LteUePhy> phy)
+LteEnbPhy::AddUePhy (uint16_t rnti)
{
- NS_LOG_FUNCTION (this);
- std::map <uint16_t, Ptr<LteUePhy> >::iterator it;
+ NS_LOG_FUNCTION (this << rnti);
+ std::set <uint16_t>::iterator it;
it = m_ueAttached.find (rnti);
if (it == m_ueAttached.end ())
{
- m_ueAttached.insert (std::pair<uint16_t, Ptr<LteUePhy> > (rnti, phy));
+ m_ueAttached.insert (rnti);
return (true);
}
else
@@ -303,8 +322,8 @@
bool
LteEnbPhy::DeleteUePhy (uint16_t rnti)
{
- NS_LOG_FUNCTION (this);
- std::map <uint16_t, Ptr<LteUePhy> >::iterator it;
+ NS_LOG_FUNCTION (this << rnti);
+ std::set <uint16_t>::iterator it;
it = m_ueAttached.find (rnti);
if (it == m_ueAttached.end ())
{
@@ -342,13 +361,20 @@
}
void
-LteEnbPhy::DoSetDownlinkSubChannels ()
+LteEnbPhy::SetDownlinkSubChannels (std::vector<int> mask)
{
NS_LOG_FUNCTION (this);
+ m_listOfDownlinkSubchannel = mask;
Ptr<SpectrumValue> txPsd = CreateTxPowerSpectralDensity ();
m_downlinkSpectrumPhy->SetTxPowerSpectralDensity (txPsd);
}
+std::vector<int>
+LteEnbPhy::GetDownlinkSubChannels (void)
+{
+ NS_LOG_FUNCTION (this);
+ return m_listOfDownlinkSubchannel;
+}
Ptr<SpectrumValue>
LteEnbPhy::CreateTxPowerSpectralDensity ()
@@ -369,7 +395,7 @@
void
-LteEnbPhy::DoSendIdealControlMessage (Ptr<IdealControlMessage> msg)
+LteEnbPhy::DoSendLteControlMessage (Ptr<LteControlMessage> msg)
{
NS_LOG_FUNCTION (this << msg);
// queues the message (wait for MAC-PHY delay)
@@ -379,10 +405,23 @@
void
-LteEnbPhy::ReceiveIdealControlMessage (Ptr<IdealControlMessage> msg)
+LteEnbPhy::ReceiveLteControlMessage (Ptr<LteControlMessage> msg)
{
+ NS_FATAL_ERROR ("Obsolete function");
NS_LOG_FUNCTION (this << msg);
- m_enbPhySapUser->ReceiveIdealControlMessage (msg);
+ m_enbPhySapUser->ReceiveLteControlMessage (msg);
+}
+
+void
+LteEnbPhy::ReceiveLteControlMessageList (std::list<Ptr<LteControlMessage> > msgList)
+{
+ NS_LOG_FUNCTION (this);
+ std::list<Ptr<LteControlMessage> >::iterator it;
+ for (it = msgList.begin (); it != msgList.end(); it++)
+ {
+ m_enbPhySapUser->ReceiveLteControlMessage (*it);
+ }
+
}
@@ -405,55 +444,59 @@
NS_LOG_FUNCTION (this);
++m_nrSubFrames;
+ if (m_srsPeriodicity>0)
+ {
+ // might be 0 in case the eNB has no UEs attached
+ m_currentSrsOffset = (m_currentSrsOffset + 1) % m_srsPeriodicity;
+ }
NS_LOG_INFO ("-----sub frame " << m_nrSubFrames << "-----");
+
// update info on TB to be received
- std::list<UlDciIdealControlMessage> uldcilist = DequeueUlDci ();
- std::list<UlDciIdealControlMessage>::iterator dciIt = uldcilist.begin ();
+ std::list<UlDciLteControlMessage> uldcilist = DequeueUlDci ();
+ std::list<UlDciLteControlMessage>::iterator dciIt = uldcilist.begin ();
+ m_ulRntiRxed.clear ();
+ NS_LOG_DEBUG (this << " eNB Expected TBs " << uldcilist.size ());
for (dciIt = uldcilist.begin (); dciIt!=uldcilist.end (); dciIt++)
- {
- std::map <uint16_t, Ptr<LteUePhy> >::iterator it2;
- it2 = m_ueAttached.find ((*dciIt).GetDci ().m_rnti);
-
- if (it2 == m_ueAttached.end ())
- {
- NS_LOG_ERROR ("UE not attached");
- }
- else
{
- // send info of TB to LteSpectrumPhy
- // translate to allocation map
- std::vector <int> rbMap;
- for (int i = (*dciIt).GetDci ().m_rbStart; i < (*dciIt).GetDci ().m_rbStart + (*dciIt).GetDci ().m_rbLen; i++)
- {
- rbMap.push_back (i);
- }
- m_uplinkSpectrumPhy->AddExpectedTb ((*dciIt).GetDci ().m_rnti, (*dciIt).GetDci ().m_tbSize, (*dciIt).GetDci ().m_mcs, rbMap, 0 /* always SISO*/);
+ std::set <uint16_t>::iterator it2;
+ it2 = m_ueAttached.find ((*dciIt).GetDci ().m_rnti);
+
+ if (it2 == m_ueAttached.end ())
+ {
+ NS_LOG_ERROR ("UE not attached");
+ }
+ else
+ {
+ // send info of TB to LteSpectrumPhy
+ // translate to allocation map
+ std::vector <int> rbMap;
+ for (int i = (*dciIt).GetDci ().m_rbStart; i < (*dciIt).GetDci ().m_rbStart + (*dciIt).GetDci ().m_rbLen; i++)
+ {
+ rbMap.push_back (i);
+ }
+ m_uplinkSpectrumPhy->AddExpectedTb ((*dciIt).GetDci ().m_rnti, (*dciIt).GetDci ().m_tbSize, (*dciIt).GetDci ().m_mcs, rbMap, 0 /* always SISO*/);
+ m_ulRntiRxed.push_back ((*dciIt).GetDci ().m_rnti);
+ }
}
- }
- // send the current burst of control messages
- std::list<Ptr<IdealControlMessage> > ctrlMsg = GetControlMessages ();
- std::vector <int> dlRb;
+ // process the current burst of control messages
+ std::list<Ptr<LteControlMessage> > ctrlMsg = GetControlMessages ();
+ std::list<DlDciListElement_s> dlDci;
+ std::list<UlDciListElement_s> ulDci;
+// std::vector <int> dlRb;
+ m_dlDataRbMap.clear ();
if (ctrlMsg.size () > 0)
{
- std::list<Ptr<IdealControlMessage> >::iterator it;
+ std::list<Ptr<LteControlMessage> >::iterator it;
it = ctrlMsg.begin ();
while (it != ctrlMsg.end ())
{
- Ptr<IdealControlMessage> msg = (*it);
- if (msg->GetMessageType () == IdealControlMessage::DL_DCI)
+ Ptr<LteControlMessage> msg = (*it);
+ if (msg->GetMessageType () == LteControlMessage::DL_DCI)
{
- std::map <uint16_t, Ptr<LteUePhy> >::iterator it2;
- Ptr<DlDciIdealControlMessage> dci = DynamicCast<DlDciIdealControlMessage> (msg);
- it2 = m_ueAttached.find (dci->GetDci ().m_rnti);
-
- if (it2 == m_ueAttached.end ())
- {
- NS_LOG_ERROR ("UE not attached");
- }
- else
- {
+ Ptr<DlDciLteControlMessage> dci = DynamicCast<DlDciLteControlMessage> (msg);
+ dlDci.push_back (dci->GetDci ());
// get the tx power spectral density according to DL-DCI(s)
// translate the DCI to Spectrum framework
uint32_t mask = 0x1;
@@ -463,63 +506,72 @@
{
for (int k = 0; k < GetRbgSize (); k++)
{
- dlRb.push_back ((i * GetRbgSize ()) + k);
+ m_dlDataRbMap.push_back ((i * GetRbgSize ()) + k);
//NS_LOG_DEBUG(this << " [enb]DL-DCI allocated PRB " << (i*GetRbgSize()) + k);
}
}
mask = (mask << 1);
}
- (*it2).second->ReceiveIdealControlMessage (msg);
- }
}
- else if (msg->GetMessageType () == IdealControlMessage::UL_DCI)
+ else if (msg->GetMessageType () == LteControlMessage::UL_DCI)
{
- std::map <uint16_t, Ptr<LteUePhy> >::iterator it2;
- Ptr<UlDciIdealControlMessage> dci = DynamicCast<UlDciIdealControlMessage> (msg);
-// QueueUlDci (*dci);
- it2 = m_ueAttached.find (dci->GetDci ().m_rnti);
+ Ptr<UlDciLteControlMessage> dci = DynamicCast<UlDciLteControlMessage> (msg);
+ QueueUlDci (*dci);
+ ulDci.push_back (dci->GetDci ());
+ }
+ it++;
- if (it2 == m_ueAttached.end ())
- {
- NS_LOG_ERROR ("UE not attached");
- }
- else
- {
- (*it2).second->ReceiveIdealControlMessage (msg);
- QueueUlDci (*dci);
- }
- }
- ctrlMsg.pop_front ();
- it = ctrlMsg.begin ();
}
}
- // set the current tx power spectral density
- SetDownlinkSubChannels (dlRb);
- // send the current burts of packets
+
+ SendControlChannels (ctrlMsg);
+
+ // send data frame
Ptr<PacketBurst> pb = GetPacketBurst ();
if (pb)
{
- NS_LOG_LOGIC (this << " eNB start TX");
- m_downlinkSpectrumPhy->StartTx (pb);
+ Simulator::Schedule (DL_CTRL_DELAY_FROM_SUBFRAME_START, // ctrl frame fixed to 3 symbols
+ &LteEnbPhy::SendDataChannels,
+ this,pb);
}
// trigger the MAC
m_enbPhySapUser->SubframeIndication (m_nrFrames, m_nrSubFrames);
-
- // trigger the UE(s)
- std::map <uint16_t, Ptr<LteUePhy> >::iterator it;
- for (it = m_ueAttached.begin (); it != m_ueAttached.end (); it++)
- {
- (*it).second->SubframeIndication (m_nrFrames, m_nrSubFrames);
- }
-
Simulator::Schedule (Seconds (GetTti ()),
&LteEnbPhy::EndSubFrame,
this);
}
+void
+LteEnbPhy::SendControlChannels (std::list<Ptr<LteControlMessage> > ctrlMsgList)
+{
+ NS_LOG_FUNCTION (this << " eNB " << m_cellId << " start tx ctrl frame");
+ // set the current tx power spectral density (full bandwidth)
+ std::vector <int> dlRb;
+ for (uint8_t i = 0; i < m_dlBandwidth; i++)
+ {
+ dlRb.push_back (i);
+ }
+ SetDownlinkSubChannels (dlRb);
+ NS_LOG_LOGIC (this << " eNB start TX CTRL");
+ m_downlinkSpectrumPhy->StartTxDlCtrlFrame (ctrlMsgList);
+
+}
+
+void
+LteEnbPhy::SendDataChannels (Ptr<PacketBurst> pb)
+{
+ // set the current tx power spectral density
+ SetDownlinkSubChannels (m_dlDataRbMap);
+ // send the current burts of packets
+ NS_LOG_LOGIC (this << " eNB start TX DATA");
+ std::list<Ptr<LteControlMessage> > ctrlMsgList;
+ ctrlMsgList.clear ();
+ m_downlinkSpectrumPhy->StartTxDataFrame (pb, ctrlMsgList, DL_DATA_DURATION);
+}
+
void
LteEnbPhy::EndSubFrame (void)
@@ -545,20 +597,30 @@
void
-LteEnbPhy::GenerateCqiReport (const SpectrumValue& sinr)
+LteEnbPhy::GenerateCtrlCqiReport (const SpectrumValue& sinr)
{
NS_LOG_FUNCTION (this << sinr);
- m_enbPhySapUser->UlCqiReport (CreateUlCqiReport (sinr));
+ FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi = CreateSrsCqiReport (sinr);
+ m_enbPhySapUser->UlCqiReport (ulcqi);
+}
+
+void
+LteEnbPhy::GenerateDataCqiReport (const SpectrumValue& sinr)
+{
+ NS_LOG_FUNCTION (this << sinr);
+ FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi = CreatePuschCqiReport (sinr);
+ m_enbPhySapUser->UlCqiReport (ulcqi);
}
-UlCqi_s
-LteEnbPhy::CreateUlCqiReport (const SpectrumValue& sinr)
+
+FfMacSchedSapProvider::SchedUlCqiInfoReqParameters
+LteEnbPhy::CreatePuschCqiReport (const SpectrumValue& sinr)
{
NS_LOG_FUNCTION (this << sinr);
Values::const_iterator it;
- UlCqi_s ulcqi;
- ulcqi.m_type = UlCqi_s::PUSCH;
+ FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi;
+ ulcqi.m_ulCqi.m_type = UlCqi_s::PUSCH;
int i = 0;
for (it = sinr.ConstValuesBegin (); it != sinr.ConstValuesEnd (); it++)
{
@@ -566,7 +628,7 @@
// NS_LOG_DEBUG ("ULCQI RB " << i << " value " << sinrdb);
// convert from double to fixed point notation Sxxxxxxxxxxx.xxx
int16_t sinrFp = LteFfConverter::double2fpS11dot3 (sinrdb);
- ulcqi.m_sinr.push_back (sinrFp);
+ ulcqi.m_ulCqi.m_sinr.push_back (sinrFp);
i++;
}
return (ulcqi);
@@ -610,39 +672,39 @@
LteEnbPhy::DoAddUe (uint16_t rnti)
{
NS_LOG_FUNCTION (this << rnti);
- // since for now ctrl messages are still sent directly to the UePhy
- // without passing to the channel, we need to get a pointer to the
- // UePhy. We do so by walking the whole UE list. This code will
- // eventually go away when a real control channel is implemented.
+
+ bool success = AddUePhy (rnti);
+ NS_ASSERT_MSG (success, "AddUePhy() failed");
+}
+
- Ptr<LteUePhy> uePhy;
- NodeList::Iterator listEnd = NodeList::End ();
- bool found = false;
- for (NodeList::Iterator i = NodeList::Begin (); i != listEnd; i++)
- {
- Ptr<Node> node = *i;
- int nDevs = node->GetNDevices ();
- for (int j = 0; j < nDevs; j++)
- {
- Ptr<LteUeNetDevice> ueDev = node->GetDevice (j)->GetObject <LteUeNetDevice> ();
- if (!ueDev)
- {
- continue;
- }
- else
- {
- Ptr<LteUeRrc> rrc = ueDev->GetRrc ();
- if ((rrc->GetRnti () == rnti) && (rrc->GetCellId () == m_cellId))
- {
- found = true;
- uePhy = ueDev->GetPhy ();
- }
- }
- }
- }
- NS_ASSERT_MSG (found , " Unable to find UE with RNTI=" << rnti << " cellId=" << m_cellId);
- bool success = AddUePhy (rnti, uePhy);
- NS_ASSERT_MSG (success, "AddUePhy() failed");
+FfMacSchedSapProvider::SchedUlCqiInfoReqParameters
+LteEnbPhy::CreateSrsCqiReport (const SpectrumValue& sinr)
+{
+ NS_LOG_FUNCTION (this << sinr);
+ Values::const_iterator it;
+ FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi;
+ ulcqi.m_ulCqi.m_type = UlCqi_s::SRS;
+ int i = 0;
+ for (it = sinr.ConstValuesBegin (); it != sinr.ConstValuesEnd (); it++)
+ {
+ double sinrdb = 10 * log10 ((*it));
+ // NS_LOG_DEBUG ("ULCQI RB " << i << " value " << sinrdb);
+ // convert from double to fixed point notation Sxxxxxxxxxxx.xxx
+ int16_t sinrFp = LteFfConverter::double2fpS11dot3 (sinrdb);
+ ulcqi.m_ulCqi.m_sinr.push_back (sinrFp);
+ i++;
+ }
+ // Insert the user generated the srs as a vendor specific parameter
+ NS_LOG_DEBUG (this << " ENB RX UL-CQI of " << m_srsUeOffset.at (m_currentSrsOffset));
+ VendorSpecificListElement_s vsp;
+ vsp.m_type = SRS_CQI_RNTI_VSP;
+ vsp.m_length = sizeof(SrsCqiRntiVsp);
+ Ptr<SrsCqiRntiVsp> rnti = Create <SrsCqiRntiVsp> (m_srsUeOffset.at (m_currentSrsOffset));
+ vsp.m_value = rnti;
+ ulcqi.m_vendorSpecificList.push_back (vsp);
+ return (ulcqi);
+
}
void
@@ -653,33 +715,61 @@
}
void
-LteEnbPhy::QueueUlDci (UlDciIdealControlMessage m)
+LteEnbPhy::QueueUlDci (UlDciLteControlMessage m)
{
NS_LOG_FUNCTION (this);
m_ulDciQueue.at (UL_PUSCH_TTIS_DELAY - 1).push_back (m);
}
-std::list<UlDciIdealControlMessage>
+std::list<UlDciLteControlMessage>
LteEnbPhy::DequeueUlDci (void)
{
NS_LOG_FUNCTION (this);
if (m_ulDciQueue.at (0).size ()>0)
{
- std::list<UlDciIdealControlMessage> ret = m_ulDciQueue.at (0);
+ std::list<UlDciLteControlMessage> ret = m_ulDciQueue.at (0);
m_ulDciQueue.erase (m_ulDciQueue.begin ());
- std::list<UlDciIdealControlMessage> l;
+ std::list<UlDciLteControlMessage> l;
m_ulDciQueue.push_back (l);
return (ret);
}
else
{
m_ulDciQueue.erase (m_ulDciQueue.begin ());
- std::list<UlDciIdealControlMessage> l;
+ std::list<UlDciLteControlMessage> l;
m_ulDciQueue.push_back (l);
- std::list<UlDciIdealControlMessage> emptylist;
+ std::list<UlDciLteControlMessage> emptylist;
return (emptylist);
}
}
+void
+LteEnbPhy::DoSetSrsConfigurationIndex (uint16_t rnti, uint16_t srcCi)
+{
+ NS_LOG_FUNCTION (this);
+ uint16_t p = GetSrsPeriodicity (srcCi);
+ if (p!=m_srsPeriodicity)
+ {
+ // resize the array of offset -> re-initialize variables
+ m_srsUeOffset.clear ();
+ m_srsUeOffset.resize (p, 0);
+ m_srsPeriodicity = p;
+ m_currentSrsOffset = p - 1; // for starting from 0 next subframe
+ }
+
+ NS_LOG_DEBUG (this << " ENB SRS P " << m_srsPeriodicity << " RNTI " << rnti << " offset " << GetSrsSubframeOffset (srcCi) << " CI " << srcCi);
+ std::map <uint16_t,uint16_t>::iterator it = m_srsCounter.find (rnti);
+ if (it != m_srsCounter.end ())
+ {
+ (*it).second = GetSrsSubframeOffset (srcCi) + 1;
+ }
+ else
+ {
+ m_srsCounter.insert (std::pair<uint16_t, uint16_t> (rnti, GetSrsSubframeOffset (srcCi) + 1));
+ }
+ m_srsUeOffset.at (GetSrsSubframeOffset (srcCi)) = rnti;
+
+}
+
};
--- a/src/lte/model/lte-enb-phy.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-enb-phy.h Tue Jul 31 19:18:23 2012 +0200
@@ -23,11 +23,15 @@
#define ENB_LTE_PHY_H
-#include "lte-phy.h"
-#include <ns3/ideal-control-messages.h>
+#include <ns3/lte-control-messages.h>
#include <ns3/lte-enb-phy-sap.h>
#include <ns3/lte-enb-cphy-sap.h>
+#include <ns3/lte-phy.h>
+
#include <map>
+#include <set>
+
+
namespace ns3 {
@@ -121,15 +125,24 @@
uint8_t GetMacChDelay (void) const;
/**
- * \brief Queue the MAC PDU to be sent
- * \param p the MAC PDU to sent
- */
- virtual void DoSendMacPdu (Ptr<Packet> p);
-
- virtual uint8_t DoGetMacChTtiDelay ();
+ * \brief set the resource blocks (a.k.a. sub channels) to be used in the downlink for transmission
+ *
+ * \param mask a vector of integers, if the i-th value is j it means
+ * that the j-th resource block is used for transmission in the
+ * downlink. If there is no i such that the value of the i-th
+ * element is j, it means that RB j is not used.
+ */
+ void SetDownlinkSubChannels (std::vector<int> mask );
- void DoSetDownlinkSubChannels ();
+ /**
+ *
+ * \return a vector of integers, if the i-th value is j it means
+ * that the j-th resource block is used for transmission in the
+ * downlink. If there is no i such that the value of the i-th
+ * element is j, it means that RB j is not used.
+ */
+ std::vector<int> GetDownlinkSubChannels (void);
/**
* \brief Create the PSD for TX
@@ -144,36 +157,46 @@
void CalcChannelQualityForUe (std::vector <double> sinr, Ptr<LteSpectrumPhy> ue);
/**
- * \brief Send the control message
- * \param msg the message to send
- */
- // virtual void SendIdealControlMessage (Ptr<IdealControlMessage> msg); // legacy
- /**
* \brief Receive the control message
* \param msg the received message
*/
- virtual void ReceiveIdealControlMessage (Ptr<IdealControlMessage> msg);
+ virtual void ReceiveLteControlMessage (Ptr<LteControlMessage> msg);
/**
* \brief Create the UL CQI feedback from SINR values perceived at
- * the physical layer with the signal received from eNB
+ * the physical layer with the PUSCH signal received from eNB
+ * \param sinr SINR values vector
+ */
+ FfMacSchedSapProvider::SchedUlCqiInfoReqParameters CreatePuschCqiReport (const SpectrumValue& sinr);
+
+ /**
+ * \brief Create the UL CQI feedback from SINR values perceived at
+ * the physical layer with the SRS signal received from eNB
* \param sinr SINR values vector
*/
- UlCqi_s CreateUlCqiReport (const SpectrumValue& sinr);
-
+ FfMacSchedSapProvider::SchedUlCqiInfoReqParameters CreateSrsCqiReport (const SpectrumValue& sinr);
- void DoSendIdealControlMessage (Ptr<IdealControlMessage> msg);
-
+ /**
+ * \brief Send the PDCCH and PCFICH in the first 3 symbols
+ * \param ctrlMsgList the list of control messages of PDCCH
+ */
+ void SendControlChannels (std::list<Ptr<LteControlMessage> > ctrlMsgList);
+
+ /**
+ * \brief Send the PDSCH
+ * \param pb the PacketBurst to be sent
+ */
+ void SendDataChannels (Ptr<PacketBurst> pb);
/**
* \param m the UL-CQI to be queued
*/
- void QueueUlDci (UlDciIdealControlMessage m);
+ void QueueUlDci (UlDciLteControlMessage m);
/**
* \returns the list of UL-CQI to be processed
*/
- std::list<UlDciIdealControlMessage> DequeueUlDci (void);
+ std::list<UlDciLteControlMessage> DequeueUlDci (void);
/**
@@ -197,9 +220,15 @@
* \brief PhySpectrum received a new PHY-PDU
*/
void PhyPduReceived (Ptr<Packet> p);
+
+ /**
+ * \brief PhySpectrum received a new list of LteControlMessage
+ */
+ virtual void ReceiveLteControlMessageList (std::list<Ptr<LteControlMessage> >);
// inherited from LtePhy
- virtual void GenerateCqiReport (const SpectrumValue& sinr);
+ virtual void GenerateCtrlCqiReport (const SpectrumValue& sinr);
+ virtual void GenerateDataCqiReport (const SpectrumValue& sinr);
private:
@@ -209,26 +238,43 @@
void DoSetEarfcn (uint16_t dlEarfcn, uint16_t ulEarfcn);
void DoAddUe (uint16_t rnti);
void DoSetTransmissionMode (uint16_t rnti, uint8_t txMode);
-
+
- bool AddUePhy (uint16_t rnti, Ptr<LteUePhy> phy);
+ // LteEnbPhySapProvider forwarded methods
+ void DoSendMacPdu (Ptr<Packet> p);
+ void DoSetSrsConfigurationIndex (uint16_t rnti, uint16_t srcCi);
+ void DoSendLteControlMessage (Ptr<LteControlMessage> msg);
+ uint8_t DoGetMacChTtiDelay ();
+
+ bool AddUePhy (uint16_t rnti);
bool DeleteUePhy (uint16_t rnti);
- std::map <uint16_t, Ptr<LteUePhy> > m_ueAttached;
+ std::set <uint16_t> m_ueAttached;
+
+ std::vector <int> m_listOfDownlinkSubchannel;
- std::vector< std::list<UlDciIdealControlMessage> > m_ulDciQueue; // for storing info on future receptions
+ std::vector <int> m_dlDataRbMap;
+
+ std::vector< std::list<UlDciLteControlMessage> > m_ulDciQueue; // for storing info on future receptions
LteEnbPhySapProvider* m_enbPhySapProvider;
LteEnbPhySapUser* m_enbPhySapUser;
LteEnbCphySapProvider* m_enbCphySapProvider;
LteEnbCphySapUser* m_enbCphySapUser;
+
+ std::vector <uint16_t> m_ulRntiRxed;
uint32_t m_nrFrames;
uint32_t m_nrSubFrames;
+ uint16_t m_srsPeriodicity;
+ std::map <uint16_t,uint16_t> m_srsCounter;
+ std::vector <uint16_t> m_srsUeOffset;
+ uint16_t m_currentSrsOffset;
+
};
--- a/src/lte/model/lte-enb-rrc.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-enb-rrc.cc Tue Jul 31 19:18:23 2012 +0200
@@ -42,6 +42,8 @@
#include "lte-rlc-um.h"
#include "lte-rlc-am.h"
+#include <ns3/simulator.h>
+
// WILD HACK for UE-RRC direct communications
#include <ns3/node-list.h>
#include <ns3/node.h>
@@ -49,6 +51,7 @@
#include <ns3/lte-ue-rrc.h>
+
NS_LOG_COMPONENT_DEFINE ("LteEnbRrc");
namespace ns3 {
@@ -64,7 +67,7 @@
EnbRrcMemberLteEnbCmacSapUser (LteEnbRrc* rrc);
virtual void NotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success);
- virtual void RrcConfigurationUpdateInd (LteUeConfig_t params);
+ virtual void RrcConfigurationUpdateInd (UeConfig params);
private:
LteEnbRrc* m_rrc;
@@ -82,7 +85,7 @@
}
void
-EnbRrcMemberLteEnbCmacSapUser::RrcConfigurationUpdateInd (LteUeConfig_t params)
+EnbRrcMemberLteEnbCmacSapUser::RrcConfigurationUpdateInd (UeConfig params)
{
m_rrc->DoRrcConfigurationUpdateInd (params);
}
@@ -99,15 +102,10 @@
: m_lastAllocatedId (0)
{
m_imsi = 0;
+ m_srsConfigurationIndex = 0;
+ m_transmissionMode = 0;
}
-UeInfo::UeInfo (uint64_t imsi)
- : m_lastAllocatedId (0)
-{
- m_imsi = imsi;
-}
-
-
UeInfo::~UeInfo (void)
{
@@ -139,6 +137,30 @@
m_imsi = imsi;
}
+uint16_t
+UeInfo::GetSrsConfigurationIndex (void)
+{
+ return m_srsConfigurationIndex;
+}
+
+void
+UeInfo::SetSrsConfigurationIndex (uint16_t srsConfIndex)
+{
+ m_srsConfigurationIndex = srsConfIndex;
+}
+
+uint8_t
+UeInfo::GetTransmissionMode (void)
+{
+ return m_transmissionMode;
+}
+
+void
+UeInfo::SetTransmissionMode (uint8_t txMode)
+{
+ m_transmissionMode = txMode;
+}
+
uint8_t
UeInfo::AddRadioBearer (Ptr<LteRadioBearerInfo> rbi)
{
@@ -193,7 +215,10 @@
m_s1SapProvider (0),
m_cphySapProvider (0),
m_configured (false),
- m_lastAllocatedRnti (0)
+ m_lastAllocatedRnti (0),
+ m_srsCurrentPeriodicityId (0),
+ m_lastAllocatedConfigurationIndex (0),
+ m_reconfigureUes (false)
{
NS_LOG_FUNCTION (this);
m_cmacSapUser = new EnbRrcMemberLteEnbCmacSapUser (this);
@@ -365,7 +390,7 @@
}
uint16_t
-LteEnbRrc::ConnectionRequest (uint64_t imsi)
+LteEnbRrc::DoRecvConnectionRequest (uint64_t imsi)
{
NS_LOG_FUNCTION (this);
// no Call Admission Control for now
@@ -379,27 +404,37 @@
m_s1SapProvider->InitialUeMessage (imsi, rnti);
}
+ // send RRC connection setup
+ LteUeConfig_t ueConfig;
+ ueConfig.m_rnti = rnti;
+ ueConfig.m_transmissionMode = (*it).second->GetTransmissionMode ();
+ ueConfig.m_srsConfigurationIndex = (*it).second->GetSrsConfigurationIndex ();
+ ueConfig.m_reconfigureFlag = false;
+ Ptr<LteUeRrc> ueRrc = GetUeRrcByImsi (imsi);
+ ueRrc->DoRecvConnectionSetup (ueConfig);
+
+ // configure MAC (and scheduler)
+ FfMacCschedSapProvider::CschedUeConfigReqParameters req;
+ req.m_rnti = rnti;
+ req.m_transmissionMode = (*it).second->GetTransmissionMode ();
+
+ // configure PHY
+ m_cphySapProvider->SetTransmissionMode (rnti, (*it).second->GetTransmissionMode ());
+ m_cphySapProvider->SetSrsConfigurationIndex (rnti, (*it).second->GetSrsConfigurationIndex ());
+
return rnti;
}
-
-uint16_t
-LteEnbRrc::ConnectionReestablishmentRequest (uint64_t imsi, uint16_t rnti)
+void
+LteEnbRrc::DoRecvConnectionSetupCompleted (uint16_t rnti)
{
NS_LOG_FUNCTION (this);
- // no Call Admission Control for now
- std::map<uint16_t, Ptr<UeInfo> >::iterator it = m_ueMap.find (rnti);
- NS_ASSERT_MSG (it != m_ueMap.end (), "RNTI " << rnti << " not found in eNB with cellId " << m_cellId);
-
- // this is needed because if the reestablishment comes from handover we don't know the imsi yet
- it->second->SetImsi (imsi);
+}
- if (m_s1SapProvider != 0)
- {
- m_s1SapProvider->InitialUeMessage (imsi, rnti);
- }
-
- return rnti;
+void
+LteEnbRrc::DoRecvConnectionReconfigurationCompleted (uint16_t rnti)
+{
+ NS_LOG_FUNCTION (this);
}
@@ -407,12 +442,11 @@
LteEnbRrc::AddUe ()
{
NS_LOG_FUNCTION (this);
- // no Call Admission Control for now
+
uint16_t rnti = CreateUeInfo (); // side effect: create UeInfo for this UE
NS_ASSERT_MSG (rnti != 0, "CreateUeInfo returned RNTI==0");
m_cmacSapProvider->AddUe (rnti);
- // need to do this after the present method returns, because under the hood a lookup is done for the RNTI, and otherwise the UE will not have it assigned yet
- Simulator::ScheduleNow (&LteEnbCphySapProvider::AddUe, m_cphySapProvider, rnti);
+ m_cphySapProvider->AddUe (rnti);
return rnti;
}
@@ -530,12 +564,6 @@
GetUeRrcByRnti (rnti)->SetupRadioBearer (bearer, rlcTypeId, lcid);
- // Transmission mode settings
- LteUeConfig_t ueConfig;
- ueConfig.m_rnti = rnti;
- ueConfig.m_transmissionMode = m_defaultTransmissionMode;
- DoRrcConfigurationUpdateInd (ueConfig);
-
return lcid;
}
@@ -692,6 +720,17 @@
// management of multiple UE info instances
// /////////////////////////////////////////
+// from 3GPP TS 36.213 table 8.2-1 UE Specific SRS Periodicity
+#define SRS_ENTRIES 9
+uint16_t g_srsPeriodicity[SRS_ENTRIES] = {0, 2, 5, 10, 20, 40, 80, 160, 320};
+uint16_t g_srsCiLow[SRS_ENTRIES] = {0, 0, 2, 7, 17, 37, 77, 157, 317};
+uint16_t g_srsCiHigh[SRS_ENTRIES] = {0, 1, 6, 16, 36, 76, 156, 316, 636};
+
+void
+LteEnbRrc::SetCellId (uint16_t cellId)
+{
+ m_cellId = cellId;
+}
uint16_t
LteEnbRrc::CreateUeInfo ()
@@ -704,14 +743,141 @@
if (m_ueMap.find (rnti) == m_ueMap.end ())
{
m_lastAllocatedRnti = rnti;
- m_ueMap.insert (std::pair<uint16_t, Ptr<UeInfo> > (rnti, CreateObject<UeInfo> ()));
+ Ptr<UeInfo> ueInfo = CreateObject<UeInfo> ();
+ ueInfo->SetSrsConfigurationIndex (GetNewSrsConfigurationIndex ());
+ m_ueMap.insert (std::pair<uint16_t, Ptr<UeInfo> > (rnti, ueInfo));
+ NS_LOG_DEBUG (this << " New UE RNTI " << rnti << " cellId " << m_cellId << " srs CI " << ueInfo->GetSrsConfigurationIndex ());
return rnti;
}
}
}
+
return 0;
}
+uint16_t
+LteEnbRrc::GetNewSrsConfigurationIndex ()
+{
+ NS_LOG_FUNCTION (this << m_ueSrsConfigurationIndexSet.size ());
+ // SRS
+ if (m_srsCurrentPeriodicityId==0)
+ {
+ // no UEs -> init
+ m_ueSrsConfigurationIndexSet.insert (0);
+ m_lastAllocatedConfigurationIndex = 0;
+ m_srsCurrentPeriodicityId++;
+
+ return 0;
+ }
+ NS_ASSERT (m_srsCurrentPeriodicityId < SRS_ENTRIES);
+ NS_LOG_DEBUG (this << " SRS p " << g_srsPeriodicity[m_srsCurrentPeriodicityId] << " set " << m_ueSrsConfigurationIndexSet.size ());
+ if (m_ueSrsConfigurationIndexSet.size () == g_srsPeriodicity[m_srsCurrentPeriodicityId])
+ {
+// NS_LOG_DEBUG (this << " SRS reconfigure CIs " << g_srsPeriodicity[m_srsCurrentPeriodicityId] << " to " << g_srsPeriodicity[m_srsCurrentPeriodicityId+1] << " at " << Simulator::Now ());
+ // increase the current periocity for having enough CIs
+ m_ueSrsConfigurationIndexSet.clear ();
+ m_srsCurrentPeriodicityId++;
+ NS_ASSERT (m_srsCurrentPeriodicityId < SRS_ENTRIES);
+ // update all the UE's CI
+ uint16_t srcCi = g_srsCiLow[m_srsCurrentPeriodicityId];
+ std::map<uint16_t, Ptr<UeInfo> >::iterator it;
+ for (it = m_ueMap.begin (); it != m_ueMap.end (); it++)
+ {
+ (*it).second->SetSrsConfigurationIndex (srcCi);
+ m_ueSrsConfigurationIndexSet.insert (srcCi);
+ m_lastAllocatedConfigurationIndex = srcCi;
+ srcCi++;
+ // send update to peer RRC
+ LteUeConfig_t ueConfig;
+ ueConfig.m_rnti = (*it).first;
+ ueConfig.m_transmissionMode = (*it).second->GetTransmissionMode ();
+ ueConfig.m_srsConfigurationIndex = (*it).second->GetSrsConfigurationIndex ();
+ ueConfig.m_reconfigureFlag = true;
+ NS_LOG_DEBUG (this << "\t rnti "<<ueConfig.m_rnti<< " CI " << ueConfig.m_srsConfigurationIndex);
+ PropagateRrcConnectionReconfiguration (ueConfig);
+ }
+ m_ueSrsConfigurationIndexSet.insert (m_lastAllocatedConfigurationIndex + 1);
+ m_lastAllocatedConfigurationIndex++;
+ }
+ else
+ {
+ // find a CI from the available ones
+ std::set<uint16_t>::reverse_iterator rit = m_ueSrsConfigurationIndexSet.rbegin ();
+ NS_LOG_DEBUG (this << " lower bound " << (*rit) << " of " << g_srsCiHigh[m_srsCurrentPeriodicityId]);
+ if ((*rit) <= g_srsCiHigh[m_srsCurrentPeriodicityId])
+ {
+ // got it from the upper bound
+ m_lastAllocatedConfigurationIndex = (*rit) + 1;
+ m_ueSrsConfigurationIndexSet.insert (m_lastAllocatedConfigurationIndex);
+ }
+ else
+ {
+ // look for released ones
+ for (uint16_t srcCi = g_srsCiLow[m_srsCurrentPeriodicityId]; srcCi < g_srsCiHigh[m_srsCurrentPeriodicityId]; srcCi++)
+ {
+ std::set<uint16_t>::iterator it = m_ueSrsConfigurationIndexSet.find (srcCi);
+ if (it==m_ueSrsConfigurationIndexSet.end ())
+ {
+ m_lastAllocatedConfigurationIndex = srcCi;
+ m_ueSrsConfigurationIndexSet.insert (srcCi);
+ break;
+ }
+ }
+ }
+ }
+ return m_lastAllocatedConfigurationIndex;
+
+}
+
+
+void
+LteEnbRrc::RemoveSrsConfigurationIndex (uint16_t srcCi)
+{
+ NS_LOG_FUNCTION (this << srcCi);
+ NS_FATAL_ERROR ("I though this method was unused so far...");
+ std::set<uint16_t>::iterator it = m_ueSrsConfigurationIndexSet.find (srcCi);
+ NS_ASSERT_MSG (it != m_ueSrsConfigurationIndexSet.end (), "request to remove unkwown SRS CI " << srcCi);
+ m_ueSrsConfigurationIndexSet.erase (it);
+ NS_ASSERT (m_srsCurrentPeriodicityId > 1);
+ if (m_ueSrsConfigurationIndexSet.size () < g_srsPeriodicity[m_srsCurrentPeriodicityId - 1])
+ {
+ // reduce the periodicity
+ m_ueSrsConfigurationIndexSet.clear ();
+ m_srsCurrentPeriodicityId--;
+ if (m_srsCurrentPeriodicityId==0)
+ {
+ // no active users : renitialize structures
+ m_lastAllocatedConfigurationIndex = 0;
+ }
+ else
+ {
+ // update all the UE's CI
+ uint16_t srcCi = g_srsCiLow[m_srsCurrentPeriodicityId];
+ std::map<uint16_t, Ptr<UeInfo> >::iterator it;
+ for (it = m_ueMap.begin (); it != m_ueMap.end (); it++)
+ {
+ (*it).second->SetSrsConfigurationIndex (srcCi);
+ m_ueSrsConfigurationIndexSet.insert (srcCi);
+ m_lastAllocatedConfigurationIndex = srcCi;
+ srcCi++;
+ // send update to peer RRC
+ LteUeConfig_t ueConfig;
+ ueConfig.m_rnti = (*it).first;
+ ueConfig.m_transmissionMode = (*it).second->GetTransmissionMode ();
+ ueConfig.m_srsConfigurationIndex = (*it).second->GetSrsConfigurationIndex ();
+ ueConfig.m_reconfigureFlag = false;
+ NS_LOG_DEBUG (this << "\t rnti "<<ueConfig.m_rnti<< " CI " << ueConfig.m_srsConfigurationIndex);
+
+ // avoid multiple reconfiguration during initialization
+ if (Simulator::Now ().GetNanoSeconds () != 0)
+ {
+ PropagateRrcConnectionReconfiguration (ueConfig);
+ }
+ }
+ }
+ }
+}
+
Ptr<UeInfo>
LteEnbRrc::GetUeInfo (uint16_t rnti)
{
@@ -726,29 +892,56 @@
LteEnbRrc::RemoveUeInfo (uint16_t rnti)
{
NS_LOG_FUNCTION (this << (uint32_t) rnti);
+ NS_FATAL_ERROR ("I though this method was unused so far...");
std::map <uint16_t, Ptr<UeInfo> >::iterator it = m_ueMap.find (rnti);
NS_ASSERT_MSG (it != m_ueMap.end (), "request to remove UE info with unknown rnti " << rnti);
+ RemoveSrsConfigurationIndex ((*it).second->GetSrsConfigurationIndex ());
m_ueMap.erase (it);
+ // remove SRS configuration index
}
void
-LteEnbRrc::DoRrcConfigurationUpdateInd (LteUeConfig_t params)
+LteEnbRrc::DoRrcConfigurationUpdateInd (LteEnbCmacSapUser::UeConfig cmacParams)
{
NS_LOG_FUNCTION (this);
- // up tp now only for TxMode change
- // update the peer UE-RRC on the change
+ // at this stage used only by the scheduler for updating txMode
+
+ LteUeConfig_t rrcParams;
+ rrcParams.m_rnti = cmacParams.m_rnti;
+ rrcParams.m_reconfigureFlag = true;
+ rrcParams.m_transmissionMode = cmacParams.m_transmissionMode;
+
+ // for now, the SRS CI is passed every time, so we need to overwrite the value
+ std::map<uint16_t, Ptr<UeInfo> >::iterator it;
+ it = m_ueMap.find (cmacParams.m_rnti);
+ NS_ASSERT_MSG (it!=m_ueMap.end (), "Unable to find UeInfo");
+ rrcParams.m_srsConfigurationIndex = (*it).second->GetSrsConfigurationIndex ();
+
+ // update Tx Mode info at eNB
+ (*it).second->SetTransmissionMode (cmacParams.m_transmissionMode);
+
+ rrcParams.m_reconfigureFlag = true;
+ PropagateRrcConnectionReconfiguration (rrcParams);
+}
+
+
+void
+LteEnbRrc::PropagateRrcConnectionReconfiguration (LteUeConfig_t params)
+{
+
Ptr<LteUeRrc> ueRrc = GetUeRrcByRnti (params.m_rnti);
- ueRrc->DoRrcConfigurationUpdateInd (params);
-
+ ueRrc->DoRecvConnectionReconfiguration (params);
+
// configure MAC (and scheduler)
- FfMacCschedSapProvider::CschedUeConfigReqParameters req;
+ LteEnbCmacSapProvider::UeConfig req;
req.m_rnti = params.m_rnti;
req.m_transmissionMode = params.m_transmissionMode;
- m_cmacSapProvider->RrcUpdateConfigurationReq (req);
+ m_cmacSapProvider->UeUpdateConfigurationReq (req);
// configure PHY
m_cphySapProvider->SetTransmissionMode (params.m_rnti, params.m_transmissionMode);
+ m_cphySapProvider->SetSrsConfigurationIndex (params.m_rnti, params.m_srsConfigurationIndex);
}
@@ -756,7 +949,7 @@
LteEnbRrc::GetUeRrcByImsi (uint64_t imsi)
{
NS_LOG_FUNCTION (this);
-
+
NodeList::Iterator listEnd = NodeList::End ();
bool found = false;
for (NodeList::Iterator i = NodeList::Begin (); i != listEnd; i++)
@@ -783,15 +976,40 @@
NS_ASSERT_MSG (found , " Unable to find UE with IMSI =" << imsi);
return 0;
}
+
Ptr<LteUeRrc>
LteEnbRrc::GetUeRrcByRnti (uint16_t rnti)
{
- uint64_t imsi = GetUeInfo (rnti)->GetImsi ();
- return GetUeRrcByImsi (imsi);
+ NS_LOG_FUNCTION (this);
+
+ NodeList::Iterator listEnd = NodeList::End ();
+ bool found = false;
+ for (NodeList::Iterator i = NodeList::Begin (); i != listEnd; i++)
+ {
+ Ptr<Node> node = *i;
+ int nDevs = node->GetNDevices ();
+ for (int j = 0; j < nDevs; j++)
+ {
+ Ptr<LteUeNetDevice> ueDev = node->GetDevice (j)->GetObject <LteUeNetDevice> ();
+ if (!ueDev)
+ {
+ continue;
+ }
+ else
+ {
+ Ptr<LteUeRrc> rrc = ueDev->GetRrc ();
+ if ((rrc->GetRnti () == rnti) && (rrc->GetCellId () == m_cellId))
+ {
+ return rrc;
+ }
+ }
+ }
+ }
+ NS_ASSERT_MSG (found , " Unable to find UE with RNTI=" << rnti << " cellId=" << m_cellId);
+ return 0;
}
-
} // namespace ns3
--- a/src/lte/model/lte-enb-rrc.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-enb-rrc.h Tue Jul 31 19:18:23 2012 +0200
@@ -15,8 +15,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * Author: Nicola Baldo <nbaldo@cttc.es>
- * Manuel Requena <manuel.requena@cttc.es>
+ * Authors: Nicola Baldo <nbaldo@cttc.es>
+ * Marco Miozzo <mmiozzo@cttc.es>
+ * Manuel Requena <manuel.requena@cttc.es>
*/
#ifndef LTE_ENB_RRC_H
@@ -33,6 +34,7 @@
#include <ns3/lte-enb-cphy-sap.h>
#include <map>
+#include <set>
namespace ns3 {
@@ -87,20 +89,29 @@
*/
std::map <uint8_t, Ptr<LteRadioBearerInfo> >::const_iterator RadioBearerMapEnd ();
- UeInfo (void);
- UeInfo (uint64_t imsi);
+ UeInfo ();
+
virtual ~UeInfo (void);
static TypeId GetTypeId (void);
uint64_t GetImsi (void);
+ void SetImsi (uint64_t imsi);
- void SetImsi (uint64_t imsi);
+ uint8_t GetTransmissionMode (void);
+ void SetTransmissionMode (uint8_t txMode);
+
+ uint16_t GetSrsConfigurationIndex (void);
+ void SetSrsConfigurationIndex (uint16_t srsConfIndex);
+
+
private:
std::map <uint8_t, Ptr<LteRadioBearerInfo> > m_rbMap;
uint8_t m_lastAllocatedId;
uint64_t m_imsi;
+ uint16_t m_srsConfigurationIndex;
+ uint8_t m_transmissionMode;
};
@@ -228,23 +239,30 @@
/**
- * RRC connection request by an UE
+ * receive RRC Connection Request from an UE
*
* \param imsi the id of the UE
*
* \return the RNTI identifying the UE in this cell
*/
- uint16_t ConnectionRequest (uint64_t imsi);
+ uint16_t DoRecvConnectionRequest (uint64_t imsi);
+
+ /**
+ * receive RRC Connection Setup Completed from an UE
+ *
+ * \param rnti the RNTI identifying the UE in this cell
+ */
+ void DoRecvConnectionSetupCompleted (uint16_t rnti);
/**
- * RRC connection reestablishment request by UE
+ * receive RRC Connection Reconfiguration Completed message from UE
*
- * \param imsi
* \param rnti
*
- * \return
*/
- uint16_t ConnectionReestablishmentRequest (uint64_t imsi, uint16_t rnti);
+ void DoRecvConnectionReconfigurationCompleted (uint16_t rnti);
+
+ void SetCellId (uint16_t m_cellId);
/**
* remove a UE from the cell
@@ -317,9 +335,11 @@
private:
/**
- * Add a new UE to the cell
+ * Allocate a new RNTI for a new UE. This is done in the following cases:
+ * * T-C-RNTI allocation upon contention-based MAC Random Access procedure
+ * * target cell RNTI allocation upon handover
*
- * \return the C-RNTI of the newly added UE
+ * \return the newly allocated RNTI
*/
uint16_t AddUe ();
@@ -347,17 +367,21 @@
void DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params);
// CMAC SAP methods
- void DoRrcConfigurationUpdateInd (LteUeConfig_t params);
+ void DoRrcConfigurationUpdateInd (LteEnbCmacSapUser::UeConfig params);
void DoNotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success);
// S1 SAP methods
void DoDataRadioBearerSetupRequest (EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters params);
+ void PropagateRrcConnectionReconfiguration (LteUeConfig_t ueConfig);
+
// management of multiple UE info instances
uint16_t CreateUeInfo ();
Ptr<UeInfo> GetUeInfo (uint16_t rnti);
void RemoveUeInfo (uint16_t rnti);
+ uint16_t GetNewSrsConfigurationIndex (void);
+ void RemoveSrsConfigurationIndex (uint16_t srcCi);
// methods used to talk to UE RRC directly in absence of real RRC protocol
Ptr<LteUeRrc> GetUeRrcByImsi (uint64_t imsi);
@@ -385,12 +409,17 @@
uint16_t m_cellId;
uint16_t m_lastAllocatedRnti;
- std::map<uint16_t, Ptr<UeInfo> > m_ueMap;
+ std::map<uint16_t, Ptr<UeInfo> > m_ueMap;
uint8_t m_defaultTransmissionMode;
enum LteEpsBearerToRlcMapping_t m_epsBearerToRlcMapping;
-
+
+ // SRS related attributes
+ uint16_t m_srsCurrentPeriodicityId;
+ std::set<uint16_t> m_ueSrsConfigurationIndexSet;
+ uint16_t m_lastAllocatedConfigurationIndex;
+ bool m_reconfigureUes;
};
--- a/src/lte/model/lte-interference.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-interference.cc Tue Jul 31 19:18:23 2012 +0200
@@ -81,7 +81,7 @@
}
else
{
- NS_LOG_LOGIC ("additional signal");
+ NS_LOG_LOGIC ("additional signal" << *m_rxSignal);
// receiving multiple simultaneous signals, make sure they are synchronized
NS_ASSERT (m_lastChangeTime == Now ());
// make sure they use orthogonal resource blocks
--- a/src/lte/model/lte-mi-error-model.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-mi-error-model.cc Tue Jul 31 19:18:23 2012 +0200
@@ -46,7 +46,28 @@
NS_LOG_COMPONENT_DEFINE ("LteMiErrorModel");
namespace ns3 {
+
+ // PCFICH-PDCCH Error model based on 3GPP R4-081920 "LTE PDCCH/PCFICH
+ // Demodulation Performance Results with Implementation Margin"
+ double PdcchPcfichBlerCurveXaxis[PDCCH_PCFICH_CURVE_SIZE] = {
+ -10,-9.8,-9.6, -9.4, -9.2, -9.0, -8.8, -8.6, -8.4, -8.2, -8.0,
+ -7.8, -7.6, -7.4, -7.2, -7.0, -6.8, -6.6, -6.4, -6.2, -6.0,
+ -5.8, -5.6, -5.4, -5.2, -5.0, -4.8, -4.6, -4.4, -4.2, -4.0,
+ -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0,
+ -1.8, -1.6, -1.4, -1.2, -1.0
+ };
+
+ double PdcchPcfichBlerCurveYaxis[PDCCH_PCFICH_CURVE_SIZE] = {
+ 0.922602, 0.871559, 0.82334, 0.777789, 0.734758, 0.694107, 0.655706,
+ 0.619429, 0.585159, 0.552785, 0.520927, 0.479229, 0.440869, 0.405579,
+ 0.373114, 0.343104, 0.309947,0.279994, 0.252936, 0.228492, 0.206048,
+ 0.181449, 0.159787, 0.140711, 0.123912, 0.109119, 0.0916184, 0.0769244,
+ 0.0645871, 0.0542285, 0.0454971, 0.037584, 0.0310472, 0.0256473,
+ 0.0211866, 0.0175023, 0.0144636, 0.0119524, 0.00987724, 0.00816236,
+ 0.00673821, 0.00532283, 0.00420476, 0.00332154, 0.00262385, 0.0020727
+
+ };
int TbsIndex[32] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1, -1, -1};
@@ -470,6 +491,93 @@
return errorRate;
}
+
+double
+LteMiErrorModel::GetPcfichPdcchError (const SpectrumValue& sinr)
+{
+ NS_LOG_FUNCTION (sinr);
+ double MI;
+ double MIsum = 0.0;
+ SpectrumValue sinrCopy = sinr;
+ Values::iterator sinrIt = sinrCopy.ValuesBegin ();
+ uint16_t rb = 0;
+ NS_ASSERT (sinrIt!=sinrCopy.ValuesEnd ());
+ while (sinrIt!=sinrCopy.ValuesEnd ())
+ {
+ double sinrLin = *sinrIt;
+ int tr = 0;
+ while ((tr<MI_MAP_QPSK_SIZE)&&(MI_map_qpsk_axis[tr] < sinrLin))
+ {
+ tr++;
+ }
+ if (sinrLin > MI_map_qpsk_axis[MI_MAP_QPSK_SIZE-1])
+ {
+ MI = 1;
+ }
+ else
+ {
+ NS_ASSERT_MSG (tr<MI_MAP_QPSK_SIZE, "MI map out of data");
+ MI = MI_map_qpsk[tr];
+ }
+// NS_LOG_DEBUG (" RB " << rb << " SINR " << 10*log10 (sinrLin) << " MI " << MI);
+ MIsum += MI;
+ sinrIt++;
+ rb++;
+ }
+ MI = MIsum / rb;
+ // return to the effective SINR value
+ int j = 0;
+ double esinr = 0.0;
+ while ((j<MI_MAP_QPSK_SIZE)&&(MI_map_qpsk[j] < MI))
+ {
+ j++;
+ }
+ if (MI > MI_map_qpsk[MI_MAP_QPSK_SIZE-1])
+ {
+ esinr = MI_map_qpsk_axis[MI_MAP_QPSK_SIZE-1];
+ }
+ else
+ {
+ NS_ASSERT_MSG (j<MI_MAP_QPSK_SIZE, "MI map out of data");
+ // take the closest value (when possible)
+ if (j>0)
+ {
+ if ((MI_map_qpsk[j]-MI)<(MI-MI_map_qpsk[j-1]))
+ {
+ esinr = MI_map_qpsk_axis[j];
+ }
+ else
+ {
+ esinr = MI_map_qpsk_axis[j-1];
+ }
+ }
+ else
+ {
+ esinr = MI_map_qpsk_axis[0];
+ }
+ }
+
+ double esirnDb = 10*log10 (esinr);
+// NS_LOG_DEBUG ("Effective SINR " << esirnDb << " max " << 10*log10 (MI_map_qpsk [MI_MAP_QPSK_SIZE-1]));
+ uint16_t i = 0;
+ double errorRate = 0.0;
+ while ((i<PDCCH_PCFICH_CURVE_SIZE)&&(PdcchPcfichBlerCurveXaxis[i] < esirnDb))
+ {
+ i++;
+ }
+ if (esirnDb > PdcchPcfichBlerCurveXaxis[PDCCH_PCFICH_CURVE_SIZE-1])
+ {
+ errorRate = 0.0;
+ }
+ else
+ {
+ NS_ASSERT_MSG (i<PDCCH_PCFICH_CURVE_SIZE, "PDCCH-PCFICH map out of data");
+ errorRate = PdcchPcfichBlerCurveYaxis[i];
+ }
+
+ return (errorRate);
+}
+
} // namespace ns3
--- a/src/lte/model/lte-mi-error-model.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-mi-error-model.h Tue Jul 31 19:18:23 2012 +0200
@@ -44,6 +44,7 @@
namespace ns3 {
+ const uint16_t PDCCH_PCFICH_CURVE_SIZE = 46;
const uint16_t MI_MAP_QPSK_SIZE = 766;
const uint16_t MI_MAP_16QAM_SIZE = 843;
const uint16_t MI_MAP_64QAM_SIZE = 725;
@@ -62,7 +63,7 @@
* \brief find the mmib (mean mutual information per bit) for different modulations of the specified TB
* \param sinr the perceived sinrs in the whole bandwidth
* \param map the actives RBs for the TB
- * \param cms the MCS of the TB
+ * \param mcs the MCS of the TB
* \return the mmib
*/
static double Mib (const SpectrumValue& sinr, const std::vector<int>& map, uint8_t mcs);
@@ -71,16 +72,26 @@
* \param mmib mean mutual information per bit of a code-block
* \param mcs the MCS
* \param cbSize the size of the CB
- * \return the bler
+ * \return the code block error rate
*/
static double MappingMiBler (double mib, uint8_t mcs, uint16_t cbSize);
/**
* \brief run the error-model algorithm for the specified TB
- * \param modulation the modulations (qpsk, 16-qam, 64-qam)
- * \param code block-size and code-rate
+ * \param sinr the perceived sinrs in the whole bandwidth
+ * \param map the actives RBs for the TB
+ * \param size the size in bytes of the TB
+ * \param mcs the MCS of the TB
+ * \return the TB error rate
*/
static double GetTbError (const SpectrumValue& sinr, const std::vector<int>& map, uint16_t size, uint8_t mcs);
+
+ /**
+ * \brief run the error-model algorithm for the specified PCFICH+PDCCH channels
+ * \param sinr the perceived sinrs in the whole bandwidth
+ * \return the decodification error of the PCFICH+PDCCH channels
+ */
+ static double GetPcfichPdcchError (const SpectrumValue& sinr);
//private:
--- a/src/lte/model/lte-net-device.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-net-device.h Tue Jul 31 19:18:23 2012 +0200
@@ -28,7 +28,7 @@
#include <ns3/traced-callback.h>
#include <ns3/nstime.h>
#include <ns3/lte-phy.h>
-#include <ns3/ideal-control-messages.h>
+#include <ns3/lte-control-messages.h>
namespace ns3 {
--- a/src/lte/model/lte-phy.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-phy.cc Tue Jul 31 19:18:23 2012 +0200
@@ -35,6 +35,7 @@
NS_OBJECT_ENSURE_REGISTERED (LtePhy);
+
LtePhy::LtePhy ()
{
NS_LOG_FUNCTION (this);
@@ -48,7 +49,8 @@
m_ulBandwidth (0),
m_dlBandwidth (0),
m_rbgSize (0),
- m_macChTtiDelay (0)
+ m_macChTtiDelay (0),
+ m_cellId (0)
{
NS_LOG_FUNCTION (this);
}
@@ -126,53 +128,6 @@
}
void
-LtePhy::SetDownlinkSubChannels (std::vector<int> mask )
-{
- NS_LOG_FUNCTION (this);
- m_listOfDownlinkSubchannel = mask;
- DoSetDownlinkSubChannels ();
-}
-
-
-void
-LtePhy::DoSetDownlinkSubChannels ()
-{
- NS_LOG_FUNCTION (this);
-}
-
-
-void
-LtePhy::SetUplinkSubChannels (std::vector<int> mask )
-{
- NS_LOG_FUNCTION (this);
- m_listOfUplinkSubchannel = mask;
- DoSetUplinkSubChannels ();
-}
-
-
-void
-LtePhy::DoSetUplinkSubChannels ()
-{
- NS_LOG_FUNCTION (this);
-}
-
-
-std::vector<int>
-LtePhy::GetDownlinkSubChannels (void)
-{
- NS_LOG_FUNCTION (this);
- return m_listOfDownlinkSubchannel;
-}
-
-
-std::vector<int>
-LtePhy::GetUplinkSubChannels (void)
-{
- NS_LOG_FUNCTION (this);
- return m_listOfUplinkSubchannel;
-}
-
-void
LtePhy::SetTti (double tti)
{
NS_LOG_FUNCTION (this << tti);
@@ -187,6 +142,43 @@
return m_tti;
}
+
+uint16_t
+LtePhy::GetSrsPeriodicity (uint16_t srcCi) const
+{
+ // from 3GPP TS 36.213 table 8.2-1 UE Specific SRS Periodicity
+ uint16_t SrsPeriodicity[9] = {0, 2, 5, 10, 20, 40, 80, 160, 320};
+ uint16_t SrsCiLow[9] = {0, 0, 2, 7, 17, 37, 77, 157, 317};
+ uint16_t SrsCiHigh[9] = {0, 1, 6, 16, 36, 76, 156, 316, 636};
+ uint8_t i;
+ for (i = 8; i > 0; i --)
+ {
+ if ((srcCi>=SrsCiLow[i])&&(srcCi<=SrsCiHigh[i]))
+ {
+ break;
+ }
+ }
+ return SrsPeriodicity[i];
+}
+
+uint16_t
+LtePhy::GetSrsSubframeOffset (uint16_t srcCi) const
+{
+ // from 3GPP TS 36.213 table 8.2-1 UE Specific SRS Periodicity
+ uint16_t SrsSubframeOffset[9] = {0, 0, 2, 7, 17, 37, 77, 157, 317};
+ uint16_t SrsCiLow[9] = {0, 0, 2, 7, 17, 37, 77, 157, 317};
+ uint16_t SrsCiHigh[9] = {0, 1, 6, 16, 36, 76, 156, 316, 636};
+ uint8_t i;
+ for (i = 8; i > 0; i --)
+ {
+ if ((srcCi>=SrsCiLow[i])&&(srcCi<=SrsCiHigh[i]))
+ {
+ break;
+ }
+ }
+ return (srcCi - SrsSubframeOffset[i]);
+}
+
uint8_t
LtePhy::GetRbgSize (void) const
{
@@ -219,31 +211,31 @@
void
-LtePhy::SetControlMessages (Ptr<IdealControlMessage> m)
+LtePhy::SetControlMessages (Ptr<LteControlMessage> m)
{
// In uplink the queue of control messages and packet are of different sizes
// for avoiding TTI cancellation due to synchronization of subframe triggers
m_controlMessagesQueue.at (m_controlMessagesQueue.size () - 1).push_back (m);
}
-std::list<Ptr<IdealControlMessage> >
+std::list<Ptr<LteControlMessage> >
LtePhy::GetControlMessages (void)
{
NS_LOG_FUNCTION (this);
if (m_controlMessagesQueue.at (0).size () > 0)
{
- std::list<Ptr<IdealControlMessage> > ret = m_controlMessagesQueue.at (0);
+ std::list<Ptr<LteControlMessage> > ret = m_controlMessagesQueue.at (0);
m_controlMessagesQueue.erase (m_controlMessagesQueue.begin ());
- std::list<Ptr<IdealControlMessage> > newlist;
+ std::list<Ptr<LteControlMessage> > newlist;
m_controlMessagesQueue.push_back (newlist);
return (ret);
}
else
{
m_controlMessagesQueue.erase (m_controlMessagesQueue.begin ());
- std::list<Ptr<IdealControlMessage> > newlist;
+ std::list<Ptr<LteControlMessage> > newlist;
m_controlMessagesQueue.push_back (newlist);
- std::list<Ptr<IdealControlMessage> > emptylist;
+ std::list<Ptr<LteControlMessage> > emptylist;
return (emptylist);
}
}
--- a/src/lte/model/lte-phy.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-phy.h Tue Jul 31 19:18:23 2012 +0200
@@ -39,7 +39,9 @@
class PacketBurst;
class LteNetDevice;
-class IdealControlMessage;
+class LteControlMessage;
+
+
/**
* \ingroup lte
@@ -109,41 +111,6 @@
*/
void SetUplinkChannel (Ptr<SpectrumChannel> c);
- /**
- * \brief set a list of sub channel to use in the downlink.
- * A sub channel is composed by a couple of resource bloks (180KHz x 1 ms)
- * \param mask a vector of intefer values. Each elements of this vector carries information about
- * the corresponding DL sub channel. If the i-th value of mask is equal to 1 (0) it means that the corresponding sub channel is used (not used) for the downlink.
- */
- void SetDownlinkSubChannels (std::vector<int> mask );
- /**
- * \brief do some operation after the set of a list of DL sub channels
- */
- virtual void DoSetDownlinkSubChannels ();
-
- /**
- * \brief set a list of sub channel to use in the uplink.
- * A sub channel is composed by a couple of resource bloks (180KHz x 1 ms)
- * \param mask a vector of intefer values. Each elements of this vector carries information about
- * the corresponding UL sub channel. If the i-th value of mask is equal to 1 (0) it means that the corresponding sub channel is used (not used) for the uplink.
- */
- void SetUplinkSubChannels (std::vector<int> mask);
- /**
- * \brief do some operation after the set of a list of UL sub channels
- */
- virtual void DoSetUplinkSubChannels ();
-
- /**
- * \brief get a list of sub channel to use in the downlink
- * \return
- */
- std::vector<int> GetDownlinkSubChannels (void);
- /**
- * \brief get a list of sub channel to use in the downlink
- * \return
- */
- std::vector<int> GetUplinkSubChannels (void);
-
/**
* \brief Compute the TX Power Spectral Density
@@ -154,10 +121,10 @@
void DoDispose ();
/**
- * \brief Receive SendIdealControlMessage (PDCCH map, CQI feedbacks) using the ideal control channel
+ * \brief Receive SendLteControlMessage (PDCCH map, CQI feedbacks) using the ideal control channel
* \param msg the Ideal Control Message to receive
*/
- virtual void ReceiveIdealControlMessage (Ptr<IdealControlMessage> msg) = 0;
+// virtual void ReceiveLteControlMessage (Ptr<LteControlMessage> msg) = 0;
/**
@@ -180,6 +147,19 @@
* \returns the RB gruop size according to the bandwidth
*/
uint8_t GetRbgSize (void) const;
+
+
+ /**
+ * \returns the SRS periodicity (see Table 8.2-1 of 36.213)
+ * \param srcCi the SRS Configuration Index
+ */
+ uint16_t GetSrsPeriodicity (uint16_t srcCi) const;
+
+ /**
+ * \returns the SRS Subframe offset (see Table 8.2-1 of 36.213)
+ * \param srcCi the SRS Configuration Index
+ */
+ uint16_t GetSrsSubframeOffset (uint16_t srcCi) const;
/**
@@ -195,20 +175,28 @@
/**
* \param m the control message to be sent
*/
- void SetControlMessages (Ptr<IdealControlMessage> m);
+ void SetControlMessages (Ptr<LteControlMessage> m);
/**
* \returns the list of control messages to be sent
*/
- std::list<Ptr<IdealControlMessage> > GetControlMessages (void);
+ std::list<Ptr<LteControlMessage> > GetControlMessages (void);
/**
- * generate a CQI report based on the given SINR
+ * generate a CQI report based on the given SINR of Ctrl frame
*
* \param sinr the SINR vs frequency measured by the device
*/
- virtual void GenerateCqiReport (const SpectrumValue& sinr) = 0;
+ virtual void GenerateCtrlCqiReport (const SpectrumValue& sinr) = 0;
+
+ /**
+ * generate a CQI report based on the given SINR of Data frame
+ * (used for PUSCH CQIs)
+ *
+ * \param sinr the SINR vs frequency measured by the device
+ */
+ virtual void GenerateDataCqiReport (const SpectrumValue& sinr) = 0;
@@ -218,9 +206,6 @@
Ptr<LteSpectrumPhy> m_downlinkSpectrumPhy;
Ptr<LteSpectrumPhy> m_uplinkSpectrumPhy;
- std::vector <int> m_listOfDownlinkSubchannel;
- std::vector <int> m_listOfUplinkSubchannel;
-
double m_txPower;
double m_noiseFigure;
@@ -233,7 +218,7 @@
uint16_t m_ulEarfcn;
std::vector< Ptr<PacketBurst> > m_packetBurstQueue;
- std::vector< std::list<Ptr<IdealControlMessage> > > m_controlMessagesQueue;
+ std::vector< std::list<Ptr<LteControlMessage> > > m_controlMessagesQueue;
uint8_t m_macChTtiDelay; // delay between MAC and channel layer in terms of TTIs
uint16_t m_cellId;
--- a/src/lte/model/lte-radio-bearer-info.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-radio-bearer-info.h Tue Jul 31 19:18:23 2012 +0200
@@ -18,6 +18,8 @@
* Author: Nicola Baldo <nbaldo@cttc.es>
*/
+#ifndef LTE_RADIO_BEARER_INFO_H
+#define LTE_RADIO_BEARER_INFO_H
#include <ns3/object.h>
#include <ns3/pointer.h>
@@ -48,3 +50,6 @@
} // namespace ns3
+
+
+#endif // LTE_RADIO_BEARER_INFO_H
--- a/src/lte/model/lte-sinr-chunk-processor.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-sinr-chunk-processor.cc Tue Jul 31 19:18:23 2012 +0200
@@ -16,6 +16,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Nicola Baldo <nbaldo@cttc.es>
+ * Modified by : Marco Miozzo <mmiozzo@cttc.es>
+ * (move from CQI to Ctrl and Data SINR Chunk processors
*/
@@ -33,22 +35,32 @@
}
-LteCqiSinrChunkProcessor::LteCqiSinrChunkProcessor (Ptr<LtePhy> p)
- : m_phy (p)
+LteCtrlSinrChunkProcessor::LteCtrlSinrChunkProcessor (Ptr<LtePhy> p)
+ : m_phy (p),
+ m_spectrumPhy (0)
{
NS_LOG_FUNCTION (this << p);
NS_ASSERT (m_phy);
}
+LteCtrlSinrChunkProcessor::LteCtrlSinrChunkProcessor (Ptr<LtePhy> p, Ptr<LteSpectrumPhy> s)
+: m_phy (p),
+ m_spectrumPhy (s)
+{
+ NS_LOG_FUNCTION (this << p);
+ NS_ASSERT (m_phy);
+ NS_ASSERT (m_spectrumPhy);
+}
-LteCqiSinrChunkProcessor::~LteCqiSinrChunkProcessor ()
+
+LteCtrlSinrChunkProcessor::~LteCtrlSinrChunkProcessor ()
{
NS_LOG_FUNCTION (this);
}
void
-LteCqiSinrChunkProcessor::Start ()
+LteCtrlSinrChunkProcessor::Start ()
{
NS_LOG_FUNCTION (this);
m_sumSinr = 0;
@@ -57,7 +69,7 @@
void
-LteCqiSinrChunkProcessor::EvaluateSinrChunk (const SpectrumValue& sinr, Time duration)
+LteCtrlSinrChunkProcessor::EvaluateSinrChunk (const SpectrumValue& sinr, Time duration)
{
NS_LOG_FUNCTION (this << sinr << duration);
if (m_sumSinr == 0)
@@ -69,12 +81,16 @@
}
void
-LteCqiSinrChunkProcessor::End ()
+LteCtrlSinrChunkProcessor::End ()
{
NS_LOG_FUNCTION (this);
if (m_totDuration.GetSeconds () > 0)
{
- m_phy->GenerateCqiReport ((*m_sumSinr) / m_totDuration.GetSeconds ());
+ m_phy->GenerateCtrlCqiReport ((*m_sumSinr) / m_totDuration.GetSeconds ());
+ if (m_spectrumPhy)
+ {
+ m_spectrumPhy->UpdateSinrPerceived ((*m_sumSinr) / m_totDuration.GetSeconds ());
+ }
}
else
{
@@ -85,22 +101,34 @@
-LtePemSinrChunkProcessor::LtePemSinrChunkProcessor (Ptr<LteSpectrumPhy> p)
-: m_phy (p)
+LteDataSinrChunkProcessor::LteDataSinrChunkProcessor (Ptr<LteSpectrumPhy> s, Ptr<LtePhy> p)
+: m_spectrumPhy (s),
+ m_phy (p)
{
NS_LOG_FUNCTION (this << p);
+ NS_ASSERT (m_spectrumPhy);
NS_ASSERT (m_phy);
}
+LteDataSinrChunkProcessor::LteDataSinrChunkProcessor (Ptr<LteSpectrumPhy> p)
+: m_spectrumPhy (p),
+ m_phy (0)
+{
+ NS_LOG_FUNCTION (this << p);
+ NS_ASSERT (m_spectrumPhy);
+
+}
-LtePemSinrChunkProcessor::~LtePemSinrChunkProcessor ()
+
+
+LteDataSinrChunkProcessor::~LteDataSinrChunkProcessor ()
{
NS_LOG_FUNCTION (this);
}
void
-LtePemSinrChunkProcessor::Start ()
+LteDataSinrChunkProcessor::Start ()
{
NS_LOG_FUNCTION (this);
m_sumSinr = 0;
@@ -109,7 +137,7 @@
void
-LtePemSinrChunkProcessor::EvaluateSinrChunk (const SpectrumValue& sinr, Time duration)
+LteDataSinrChunkProcessor::EvaluateSinrChunk (const SpectrumValue& sinr, Time duration)
{
NS_LOG_FUNCTION (this << sinr << duration);
if (m_sumSinr == 0)
@@ -121,12 +149,16 @@
}
void
-LtePemSinrChunkProcessor::End ()
+LteDataSinrChunkProcessor::End ()
{
NS_LOG_FUNCTION (this);
if (m_totDuration.GetSeconds () > 0)
{
- m_phy->UpdateSinrPerceived ((*m_sumSinr) / m_totDuration.GetSeconds ());
+ m_spectrumPhy->UpdateSinrPerceived ((*m_sumSinr) / m_totDuration.GetSeconds ());
+ if (m_phy)
+ {
+ m_phy->GenerateDataCqiReport ((*m_sumSinr) / m_totDuration.GetSeconds ());
+ }
}
else
{
--- a/src/lte/model/lte-sinr-chunk-processor.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-sinr-chunk-processor.h Tue Jul 31 19:18:23 2012 +0200
@@ -16,6 +16,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Nicola Baldo <nbaldo@cttc.es>
+ * Modified by : Marco Miozzo <mmiozzo@cttc.es>
+ * (move from CQI to Ctrl and Data SINR Chunk processors)
*/
@@ -53,14 +55,18 @@
/**
- * This SinrProcessor averages the calculated SINR over time.
+ * The LteCtrlSinrChunkProcessor averages the calculated SINR over time
+ * for the Ctrl frame and therefore in charge of generating the CQI starting
+ * from the reference signals and the sinr values used for evaluating the
+ * decodification error probability of the control channels (PCFICH + PDCCH)
*
*/
-class LteCqiSinrChunkProcessor : public LteSinrChunkProcessor
+class LteCtrlSinrChunkProcessor : public LteSinrChunkProcessor
{
public:
- virtual ~LteCqiSinrChunkProcessor ();
- LteCqiSinrChunkProcessor (Ptr<LtePhy> p);
+ virtual ~LteCtrlSinrChunkProcessor ();
+ LteCtrlSinrChunkProcessor (Ptr<LtePhy> p);
+ LteCtrlSinrChunkProcessor (Ptr<LtePhy> p, Ptr<LteSpectrumPhy> s);
virtual void Start ();
virtual void EvaluateSinrChunk (const SpectrumValue& sinr, Time duration);
virtual void End ();
@@ -68,26 +74,32 @@
Ptr<SpectrumValue> m_sumSinr;
Time m_totDuration;
Ptr<LtePhy> m_phy;
+ Ptr<LteSpectrumPhy> m_spectrumPhy;
};
/**
-* This SinrProcessor averages the calculated SINR over time for Phy error model
+* The LteDataSinrChunkProcessor averages the calculated SINR over time for
+* data frame and therefore in charge of generating the sinr values for
+* evaluating the errors of data packets. Might be used also for generating
+* CQI based on data in case any LtePhy is attached.
*
*/
-class LtePemSinrChunkProcessor : public LteSinrChunkProcessor
+class LteDataSinrChunkProcessor : public LteSinrChunkProcessor
{
public:
- virtual ~LtePemSinrChunkProcessor ();
- LtePemSinrChunkProcessor (Ptr<LteSpectrumPhy> p);
+ virtual ~LteDataSinrChunkProcessor ();
+ LteDataSinrChunkProcessor (Ptr<LteSpectrumPhy> p);
+ LteDataSinrChunkProcessor (Ptr<LteSpectrumPhy> s, Ptr<LtePhy> p);
virtual void Start ();
virtual void EvaluateSinrChunk (const SpectrumValue& sinr, Time duration);
virtual void End ();
private:
Ptr<SpectrumValue> m_sumSinr;
Time m_totDuration;
- Ptr<LteSpectrumPhy> m_phy;
+ Ptr<LteSpectrumPhy> m_spectrumPhy;
+ Ptr<LtePhy> m_phy;
};
--- a/src/lte/model/lte-spectrum-phy.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-spectrum-phy.cc Tue Jul 31 19:18:23 2012 +0200
@@ -41,7 +41,19 @@
NS_LOG_COMPONENT_DEFINE ("LteSpectrumPhy");
namespace ns3 {
-
+
+
+
+// duration of SRS portion of UL subframe
+// = 1 symbol for SRS -1ns as margin to avoid overlapping simulator events
+static const Time UL_SRS_DURATION = NanoSeconds (71429 -1);
+
+// duration of the control portion of a subframe
+// = 0.001 / 14 * 3 (ctrl fixed to 3 symbols) -1ns as margin to avoid overlapping simulator events
+static const Time DL_CTRL_DURATION = NanoSeconds (214286 -1);
+
+
+
TbId_t::TbId_t ()
{
@@ -73,7 +85,8 @@
m_transmissionMode (0)
{
NS_LOG_FUNCTION (this);
- m_interference = CreateObject<LteInterference> ();
+ m_interferenceData = CreateObject<LteInterference> ();
+ m_interferenceCtrl = CreateObject<LteInterference> ();
for (uint8_t i = 0; i < 7; i++)
{
m_txModeGain.push_back (1.0);
@@ -94,11 +107,15 @@
m_channel = 0;
m_mobility = 0;
m_device = 0;
- m_interference->Dispose ();
- m_interference = 0;
- m_genericPhyTxEndCallback = MakeNullCallback< void, Ptr<const Packet> > ();
- m_genericPhyRxEndErrorCallback = MakeNullCallback< void > ();
- m_genericPhyRxEndOkCallback = MakeNullCallback< void, Ptr<Packet> > ();
+ m_interferenceData->Dispose ();
+ m_interferenceData = 0;
+ m_interferenceCtrl->Dispose ();
+ m_interferenceCtrl = 0;
+ m_ltePhyTxEndCallback = MakeNullCallback< void, Ptr<const Packet> > ();
+ m_ltePhyRxDataEndErrorCallback = MakeNullCallback< void > ();
+ m_ltePhyRxDataEndOkCallback = MakeNullCallback< void, Ptr<Packet> > ();
+ m_ltePhyRxCtrlEndOkCallback = MakeNullCallback< void, std::list<Ptr<LteControlMessage> > > ();
+ m_ltePhyRxCtrlEndErrorCallback = MakeNullCallback< void > ();
SpectrumPhy::DoDispose ();
}
@@ -109,8 +126,11 @@
case LteSpectrumPhy::IDLE:
os << "IDLE";
break;
- case LteSpectrumPhy::RX:
- os << "RX";
+ case LteSpectrumPhy::RX_DATA:
+ os << "RX_DATA";
+ break;
+ case LteSpectrumPhy::RX_CTRL:
+ os << "RX_CTRL";
break;
case LteSpectrumPhy::TX:
os << "TX";
@@ -122,7 +142,6 @@
return os;
}
-
TypeId
LteSpectrumPhy::GetTypeId (void)
{
@@ -143,10 +162,15 @@
.AddTraceSource ("RxEndError",
"Trace fired when a previosuly started RX terminates with an error",
MakeTraceSourceAccessor (&LteSpectrumPhy::m_phyRxEndErrorTrace))
- .AddAttribute ("PemEnabled",
- "Activate/Deactivate the error model (by default is active).",
+ .AddAttribute ("DataErrorModelEnabled",
+ "Activate/Deactivate the error model of data (TBs of PDSCH and PUSCH) [by default is active].",
BooleanValue (true),
- MakeBooleanAccessor (&LteSpectrumPhy::m_pemEnabled),
+ MakeBooleanAccessor (&LteSpectrumPhy::m_dataErrorModelEnabled),
+ MakeBooleanChecker ())
+ .AddAttribute ("CtrlErrorModelEnabled",
+ "Activate/Deactivate the error model of control (PCFICH-PDCCH decodification) [by default is active].",
+ BooleanValue (true),
+ MakeBooleanAccessor (&LteSpectrumPhy::m_ctrlErrorModelEnabled),
MakeBooleanChecker ())
;
return tid;
@@ -215,34 +239,50 @@
NS_LOG_FUNCTION (this << noisePsd);
NS_ASSERT (noisePsd);
m_rxSpectrumModel = noisePsd->GetSpectrumModel ();
- m_interference->SetNoisePowerSpectralDensity (noisePsd);
+ m_interferenceData->SetNoisePowerSpectralDensity (noisePsd);
+ m_interferenceCtrl->SetNoisePowerSpectralDensity (noisePsd);
}
void
-LteSpectrumPhy::SetGenericPhyTxEndCallback (GenericPhyTxEndCallback c)
+LteSpectrumPhy::SetLtePhyTxEndCallback (LtePhyTxEndCallback c)
{
NS_LOG_FUNCTION (this);
- m_genericPhyTxEndCallback = c;
+ m_ltePhyTxEndCallback = c;
+}
+
+
+void
+LteSpectrumPhy::SetLtePhyRxDataEndErrorCallback (LtePhyRxDataEndErrorCallback c)
+{
+ NS_LOG_FUNCTION (this);
+ m_ltePhyRxDataEndErrorCallback = c;
}
void
-LteSpectrumPhy::SetGenericPhyRxEndErrorCallback (GenericPhyRxEndErrorCallback c)
+LteSpectrumPhy::SetLtePhyRxDataEndOkCallback (LtePhyRxDataEndOkCallback c)
{
NS_LOG_FUNCTION (this);
- m_genericPhyRxEndErrorCallback = c;
+ m_ltePhyRxDataEndOkCallback = c;
}
+void
+LteSpectrumPhy::SetLtePhyRxCtrlEndOkCallback (LtePhyRxCtrlEndOkCallback c)
+{
+ NS_LOG_FUNCTION (this);
+ m_ltePhyRxCtrlEndOkCallback = c;
+}
void
-LteSpectrumPhy::SetGenericPhyRxEndOkCallback (GenericPhyRxEndOkCallback c)
+LteSpectrumPhy::SetLtePhyRxCtrlEndErrorCallback (LtePhyRxCtrlEndErrorCallback c)
{
NS_LOG_FUNCTION (this);
- m_genericPhyRxEndOkCallback = c;
+ m_ltePhyRxCtrlEndErrorCallback = c;
}
+
Ptr<AntennaModel>
LteSpectrumPhy::GetRxAntenna ()
{
@@ -271,66 +311,174 @@
}
+
bool
-LteSpectrumPhy::StartTx (Ptr<PacketBurst> pb)
+LteSpectrumPhy::StartTxDataFrame (Ptr<PacketBurst> pb, std::list<Ptr<LteControlMessage> > ctrlMsgList, Time duration)
{
NS_LOG_FUNCTION (this << pb);
NS_LOG_LOGIC (this << " state: " << m_state);
-
+
m_phyTxStartTrace (pb);
-
+
switch (m_state)
- {
- case RX:
+ {
+ case RX_DATA:
+ case RX_CTRL:
NS_FATAL_ERROR ("cannot TX while RX: according to FDD channel acces, the physical layer for transmission cannot be used for reception");
break;
-
+
case TX:
NS_FATAL_ERROR ("cannot TX while already TX: the MAC should avoid this");
break;
-
+
case IDLE:
- {
- /*
- m_txPsd must be setted by the device, according to
- (i) the available subchannel for transmission
- (ii) the power transmission
- */
- NS_ASSERT (m_txPsd);
- m_txPacketBurst = pb;
-
- // we need to convey some PHY meta information to the receiver
- // to be used for simulation purposes (e.g., the CellId). This
- // is done by adding an LtePhyTag to the first packet in the
- // burst.
- NS_ASSERT (pb->Begin () != pb->End ());
- LtePhyTag tag (m_cellId);
- Ptr<Packet> firstPacketInBurst = *(pb->Begin ());
- firstPacketInBurst->AddPacketTag (tag);
-
- ChangeState (TX);
- NS_ASSERT (m_channel);
- double tti = 0.001;
- Ptr<LteSpectrumSignalParameters> txParams = Create<LteSpectrumSignalParameters> ();
- txParams->duration = Seconds (tti);
+ {
+ /*
+ m_txPsd must be setted by the device, according to
+ (i) the available subchannel for transmission
+ (ii) the power transmission
+ */
+ NS_ASSERT (m_txPsd);
+ m_txPacketBurst = pb;
+
+ // we need to convey some PHY meta information to the receiver
+ // to be used for simulation purposes (e.g., the CellId). This
+ // is done by setting the ctrlMsgList parameter of
+ // LteSpectrumSignalParametersDataFrame
+ ChangeState (TX);
+ NS_ASSERT (m_channel);
+ Ptr<LteSpectrumSignalParametersDataFrame> txParams = Create<LteSpectrumSignalParametersDataFrame> ();
+ txParams->duration = duration;
txParams->txPhy = GetObject<SpectrumPhy> ();
txParams->txAntenna = m_antenna;
txParams->psd = m_txPsd;
txParams->packetBurst = pb;
+ txParams->ctrlMsgList = ctrlMsgList;
+ txParams->cellId = m_cellId;
m_channel->StartTx (txParams);
- Simulator::Schedule (Seconds (tti), &LteSpectrumPhy::EndTx, this);
- }
- return false;
- break;
-
+ Simulator::Schedule (duration, &LteSpectrumPhy::EndTx, this);
+ }
+ return false;
+ break;
+
default:
- NS_FATAL_ERROR ("uknown state");
+ NS_FATAL_ERROR ("unknown state");
return true;
break;
+ }
+}
+
+bool
+LteSpectrumPhy::StartTxDlCtrlFrame (std::list<Ptr<LteControlMessage> > ctrlMsgList)
+{
+ NS_LOG_FUNCTION (this << time);
+ NS_LOG_LOGIC (this << " state: " << m_state);
+
+// m_phyTxStartTrace (pb);
+
+ switch (m_state)
+ {
+ case RX_DATA:
+ case RX_CTRL:
+ NS_FATAL_ERROR ("cannot TX while RX: according to FDD channel acces, the physical layer for transmission cannot be used for reception");
+ break;
+
+ case TX:
+ NS_FATAL_ERROR ("cannot TX while already TX: the MAC should avoid this");
+ break;
+
+ case IDLE:
+ {
+ /*
+ m_txPsd must be setted by the device, according to
+ (i) the available subchannel for transmission
+ (ii) the power transmission
+ */
+ NS_ASSERT (m_txPsd);
+
+ // we need to convey some PHY meta information to the receiver
+ // to be used for simulation purposes (e.g., the CellId). This
+ // is done by setting the cellId parameter of
+ // LteSpectrumSignalParametersDlCtrlFrame
+ ChangeState (TX);
+ NS_ASSERT (m_channel);
+
+ Ptr<LteSpectrumSignalParametersDlCtrlFrame> txParams = Create<LteSpectrumSignalParametersDlCtrlFrame> ();
+ txParams->duration = DL_CTRL_DURATION;
+ txParams->txPhy = GetObject<SpectrumPhy> ();
+ txParams->txAntenna = m_antenna;
+ txParams->psd = m_txPsd;
+ txParams->cellId = m_cellId;
+ txParams->ctrlMsgList = ctrlMsgList;
+ m_channel->StartTx (txParams);
+ Simulator::Schedule (DL_CTRL_DURATION, &LteSpectrumPhy::EndTx, this);
}
+ return false;
+ break;
+
+ default:
+ NS_FATAL_ERROR ("unknown state");
+ return true;
+ break;
+ }
}
+bool
+LteSpectrumPhy::StartTxUlSrsFrame ()
+{
+ NS_LOG_FUNCTION (this << time);
+ NS_LOG_LOGIC (this << " state: " << m_state);
+
+ // m_phyTxStartTrace (pb);
+
+ switch (m_state)
+ {
+ case RX_DATA:
+ case RX_CTRL:
+ NS_FATAL_ERROR ("cannot TX while RX: according to FDD channel acces, the physical layer for transmission cannot be used for reception");
+ break;
+
+ case TX:
+ NS_FATAL_ERROR ("cannot TX while already TX: the MAC should avoid this");
+ break;
+
+ case IDLE:
+ {
+ /*
+ m_txPsd must be setted by the device, according to
+ (i) the available subchannel for transmission
+ (ii) the power transmission
+ */
+ NS_ASSERT (m_txPsd);
+
+ // we need to convey some PHY meta information to the receiver
+ // to be used for simulation purposes (e.g., the CellId). This
+ // is done by setting the cellId parameter of
+ // LteSpectrumSignalParametersDlCtrlFrame
+ ChangeState (TX);
+ NS_ASSERT (m_channel);
+ Ptr<LteSpectrumSignalParametersUlSrsFrame> txParams = Create<LteSpectrumSignalParametersUlSrsFrame> ();
+ txParams->duration = UL_SRS_DURATION;
+ txParams->txPhy = GetObject<SpectrumPhy> ();
+ txParams->txAntenna = m_antenna;
+ txParams->psd = m_txPsd;
+ txParams->cellId = m_cellId;
+ m_channel->StartTx (txParams);
+ Simulator::Schedule (UL_SRS_DURATION, &LteSpectrumPhy::EndTx, this);
+ }
+ return false;
+ break;
+
+ default:
+ NS_FATAL_ERROR ("unknown state");
+ return true;
+ break;
+ }
+}
+
+
+
void
LteSpectrumPhy::EndTx ()
{
@@ -341,13 +489,13 @@
m_phyTxEndTrace (m_txPacketBurst);
- if (!m_genericPhyTxEndCallback.IsNull ())
+ if (!m_ltePhyTxEndCallback.IsNull ())
{
for (std::list<Ptr<Packet> >::const_iterator iter = m_txPacketBurst->Begin (); iter
!= m_txPacketBurst->End (); ++iter)
{
Ptr<Packet> packet = (*iter)->Copy ();
- m_genericPhyTxEndCallback (packet);
+ m_ltePhyTxEndCallback (packet);
}
}
@@ -361,85 +509,201 @@
{
NS_LOG_FUNCTION (this << spectrumRxParams);
NS_LOG_LOGIC (this << " state: " << m_state);
-
- // interference will happen regardless of the type of the signal (could be 3G, GSM, whatever)
+
Ptr <const SpectrumValue> rxPsd = spectrumRxParams->psd;
Time duration = spectrumRxParams->duration;
-
- m_interference->AddSignal (rxPsd, duration);
-
+
// the device might start RX only if the signal is of a type
// understood by this device - in this case, an LTE signal.
- Ptr<LteSpectrumSignalParameters> lteRxParams = DynamicCast<LteSpectrumSignalParameters> (spectrumRxParams);
- if (lteRxParams != 0)
+ Ptr<LteSpectrumSignalParametersDataFrame> lteDataRxParams = DynamicCast<LteSpectrumSignalParametersDataFrame> (spectrumRxParams);
+ if (lteDataRxParams != 0)
+ {
+ m_interferenceData->AddSignal (rxPsd, duration);
+ StartRxData (lteDataRxParams);
+ }
+ else
{
- switch (m_state)
+ Ptr<LteSpectrumSignalParametersDlCtrlFrame> lteDlCtrlRxParams = DynamicCast<LteSpectrumSignalParametersDlCtrlFrame> (spectrumRxParams);
+ Ptr<LteSpectrumSignalParametersUlSrsFrame> lteUlSrsRxParams = DynamicCast<LteSpectrumSignalParametersUlSrsFrame> (spectrumRxParams);
+ if ((lteDlCtrlRxParams!=0)||(lteUlSrsRxParams!=0))
{
- case TX:
- NS_FATAL_ERROR ("cannot RX while TX: according to FDD channel access, the physical layer for transmission cannot be used for reception");
- break;
+ m_interferenceCtrl->AddSignal (rxPsd, duration);
+ StartRxCtrl (spectrumRxParams);
+ }
+ else
+ {
+ // other type of signal (could be 3G, GSM, whatever) -> interference
+ m_interferenceData->AddSignal (rxPsd, duration);
+ m_interferenceCtrl->AddSignal (rxPsd, duration);
+ }
+ }
+
+}
- case IDLE:
- case RX:
- // the behavior is similar when
- // we're IDLE or RX because we can receive more signals
- // simultaneously (e.g., at the eNB).
+void
+LteSpectrumPhy::StartRxData (Ptr<LteSpectrumSignalParametersDataFrame> params)
+{
+ NS_LOG_FUNCTION (this);
+ switch (m_state)
+ {
+ case TX:
+ NS_FATAL_ERROR ("cannot RX while TX: according to FDD channel access, the physical layer for transmission cannot be used for reception");
+ break;
+ case RX_CTRL:
+ NS_FATAL_ERROR ("cannot RX Data while receiving control");
+ break;
+ case IDLE:
+ case RX_DATA:
+ // the behavior is similar when
+ // we're IDLE or RX because we can receive more signals
+ // simultaneously (e.g., at the eNB).
+ {
+ // To check if we're synchronized to this signal, we check
+ // for the CellId which is reported in the
+ // LteSpectrumSignalParametersDataFrame
+ if (params->cellId == m_cellId)
+ {
+ NS_LOG_LOGIC (this << " synchronized with this signal (cellId=" << params->cellId << ")");
+ if ((m_rxPacketBurstList.empty ())&&(m_rxControlMessageList.empty ()))
+ {
+ NS_ASSERT (m_state == IDLE);
+ // first transmission, i.e., we're IDLE and we
+ // start RX
+ m_firstRxStart = Simulator::Now ();
+ m_firstRxDuration = params->duration;
+ NS_LOG_LOGIC (this << " scheduling EndRx with delay " << params->duration.GetSeconds () << "s");
+ Simulator::Schedule (params->duration, &LteSpectrumPhy::EndRxData, this);
+ }
+ else
+ {
+ NS_ASSERT (m_state == RX_DATA);
+ // sanity check: if there are multiple RX events, they
+ // should occur at the same time and have the same
+ // duration, otherwise the interference calculation
+ // won't be correct
+ NS_ASSERT ((m_firstRxStart == Simulator::Now ())
+ && (m_firstRxDuration == params->duration));
+ }
+
+ ChangeState (RX_DATA);
+ if (params->packetBurst)
+ {
+ m_rxPacketBurstList.push_back (params->packetBurst);
+ m_interferenceData->StartRx (params->psd);
+
+ m_phyRxStartTrace (params->packetBurst);
+ }
+ NS_LOG_DEBUG (this << " insert msgs " << params->ctrlMsgList.size ());
+ m_rxControlMessageList.insert (m_rxControlMessageList.end (), params->ctrlMsgList.begin (), params->ctrlMsgList.end ());
+
+ NS_LOG_LOGIC (this << " numSimultaneousRxEvents = " << m_rxPacketBurstList.size ());
+ }
+ else
+ {
+ NS_LOG_LOGIC (this << " not in sync with this signal (cellId="
+ << params->cellId << ", m_cellId=" << m_cellId << ")");
+ }
+ }
+ break;
+
+ default:
+ NS_FATAL_ERROR ("unknown state");
+ break;
+ }
+
+ NS_LOG_LOGIC (this << " state: " << m_state);
+}
+
+
+
+void
+LteSpectrumPhy::StartRxCtrl (Ptr<SpectrumSignalParameters> params)
+{
+ NS_LOG_FUNCTION (this);
+ switch (m_state)
+ {
+ case TX:
+ NS_FATAL_ERROR ("cannot RX while TX: according to FDD channel access, the physical layer for transmission cannot be used for reception");
+ break;
+ case RX_DATA:
+ NS_FATAL_ERROR ("cannot RX data while receing control");
+ break;
+ case IDLE:
+ case RX_CTRL:
+ // the behavior is similar when
+ // we're IDLE or RX because we can receive more signals
+ // simultaneously (e.g., at the eNB).
+ {
+ // To check if we're synchronized to this signal, we check
+ // for the CellId which is reported in the
+ // LteSpectrumSignalParametersDlCtrlFrame
+ uint16_t cellId;
+ bool dl;
+ Ptr<LteSpectrumSignalParametersDlCtrlFrame> lteDlCtrlRxParams = DynamicCast<LteSpectrumSignalParametersDlCtrlFrame> (params);
+ if (lteDlCtrlRxParams!=0)
{
- // To check if we're synchronized to this signal, we check
- // for the CellId which is reported in the LtePhyTag
- NS_ASSERT (lteRxParams->packetBurst->Begin () != lteRxParams->packetBurst->End ());
- LtePhyTag tag;
- Ptr<Packet> firstPacketInBurst = *(lteRxParams->packetBurst->Begin ());
- firstPacketInBurst->RemovePacketTag (tag);
- if (tag.GetCellId () == m_cellId)
+ cellId = lteDlCtrlRxParams->cellId;
+ dl = true;
+ }
+ else
+ {
+ Ptr<LteSpectrumSignalParametersUlSrsFrame> lteUlSrsRxParams = DynamicCast<LteSpectrumSignalParametersUlSrsFrame> (params);
+ cellId = lteUlSrsRxParams->cellId;
+ dl = false;
+ }
+ if (cellId == m_cellId)
+ {
+ NS_LOG_LOGIC (this << " synchronized with this signal (cellId=" << cellId << ")");
+ if (m_state == IDLE)
+ {
+ // first transmission, i.e., we're IDLE and we
+ // start RX
+ NS_ASSERT (m_rxControlMessageList.empty ());
+ m_firstRxStart = Simulator::Now ();
+ m_firstRxDuration = params->duration;
+ NS_LOG_LOGIC (this << " scheduling EndRx with delay " << params->duration);
+ if (dl==true)
{
- NS_LOG_LOGIC (this << " synchronized with this signal (cellId=" << tag.GetCellId () << ")");
- if (m_rxPacketBurstList.empty ())
- {
- NS_ASSERT (m_state == IDLE);
- // first transmission, i.e., we're IDLE and we
- // start RX
- m_firstRxStart = Simulator::Now ();
- m_firstRxDuration = duration;
- NS_LOG_LOGIC (this << " scheduling EndRx with delay " << duration);
- Simulator::Schedule (duration, &LteSpectrumPhy::EndRx, this);
- }
- else
- {
- NS_ASSERT (m_state == RX);
- // sanity check: if there are multiple RX events, they
- // should occur at the same time and have the same
- // duration, otherwise the interference calculation
- // won't be correct
- NS_ASSERT ((m_firstRxStart == Simulator::Now ())
- && (m_firstRxDuration == duration));
- }
-
- ChangeState (RX);
- m_interference->StartRx (rxPsd);
-
- m_phyRxStartTrace (lteRxParams->packetBurst);
-
- m_rxPacketBurstList.push_back (lteRxParams->packetBurst);
-
- NS_LOG_LOGIC (this << " numSimultaneousRxEvents = " << m_rxPacketBurstList.size ());
+ // store the DCIs
+ m_rxControlMessageList = lteDlCtrlRxParams->ctrlMsgList;
+ Simulator::Schedule (params->duration, &LteSpectrumPhy::EndRxDlCtrl, this);
}
else
{
- NS_LOG_LOGIC (this << " not in sync with this signal (cellId="
- << tag.GetCellId () << ", m_cellId=" << m_cellId << ")");
+ Simulator::Schedule (params->duration, &LteSpectrumPhy::EndRxUlSrs, this);
}
}
- break;
+ else if (m_state == RX_CTRL)
+ {
+ // sanity check: if there are multiple RX events, they
+ // should occur at the same time and have the same
+ // duration, otherwise the interference calculation
+ // won't be correct
+ NS_ASSERT ((m_firstRxStart == Simulator::Now ())
+ && (m_firstRxDuration == params->duration));
+ }
+
+ ChangeState (RX_CTRL);
+ m_interferenceCtrl->StartRx (params->psd);
+
+// NS_LOG_LOGIC (this << " numSimultaneousRxEvents = " << m_rxPacketBurstList.size ());
+ }
+ else
+ {
+ NS_LOG_LOGIC (this << " not in sync with this signal (cellId="
+ << cellId << ", m_cellId=" << m_cellId << ")");
+ }
+ }
+ break;
+
+ default:
+ NS_FATAL_ERROR ("unknown state");
+ break;
+ }
+
+ NS_LOG_LOGIC (this << " state: " << m_state);
+}
- default:
- NS_FATAL_ERROR ("unknown state");
- break;
- }
-
- NS_LOG_LOGIC (this << " state: " << m_state);
- }
-}
void
LteSpectrumPhy::UpdateSinrPerceived (const SpectrumValue& sinr)
@@ -470,16 +734,16 @@
void
-LteSpectrumPhy::EndRx ()
+LteSpectrumPhy::EndRxData ()
{
NS_LOG_FUNCTION (this);
NS_LOG_LOGIC (this << " state: " << m_state);
- NS_ASSERT (m_state == RX);
+ NS_ASSERT (m_state == RX_DATA);
// this will trigger CQI calculation and Error Model evaluation
// as a side effect, the error model should update the error status of all TBs
- m_interference->EndRx ();
+ m_interferenceData->EndRx ();
NS_LOG_DEBUG (this << " No. of burts " << m_rxPacketBurstList.size ());
NS_LOG_DEBUG (this << " Expected TBs " << m_expectedTbs.size ());
expectedTbs_t::iterator itTb = m_expectedTbs.begin ();
@@ -491,7 +755,7 @@
while (itTb!=m_expectedTbs.end ())
{
- if (m_pemEnabled)
+ if (m_dataErrorModelEnabled)
{
double errorRate = LteMiErrorModel::GetTbError (m_sinrPerceived, (*itTb).second.rbBitmap, (*itTb).second.size, (*itTb).second.mcs);
(*itTb).second.corrupt = m_random.GetValue () > errorRate ? false : true;
@@ -504,7 +768,6 @@
// }
itTb++;
}
-
for (std::list<Ptr<PacketBurst> >::const_iterator i = m_rxPacketBurstList.begin ();
i != m_rxPacketBurstList.end (); ++i)
{
@@ -524,9 +787,9 @@
{
m_phyRxEndOkTrace (*j);
- if (!m_genericPhyRxEndOkCallback.IsNull ())
+ if (!m_ltePhyRxDataEndOkCallback.IsNull ())
{
- m_genericPhyRxEndOkCallback (*j);
+ m_ltePhyRxDataEndOkCallback (*j);
}
}
else
@@ -537,21 +800,94 @@
}
}
}
+
+ if (!m_rxControlMessageList.empty ())
+ {
+ if (!m_ltePhyRxCtrlEndOkCallback.IsNull ())
+ {
+ m_ltePhyRxCtrlEndOkCallback (m_rxControlMessageList);
+ }
+ }
ChangeState (IDLE);
m_rxPacketBurstList.clear ();
+ m_rxControlMessageList.clear ();
m_expectedTbs.clear ();
}
+
+void
+LteSpectrumPhy::EndRxDlCtrl ()
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_LOGIC (this << " state: " << m_state);
+
+ NS_ASSERT (m_state == RX_CTRL);
+
+ // this will trigger CQI calculation and Error Model evaluation
+ // as a side effect, the error model should update the error status of all TBs
+ m_interferenceCtrl->EndRx ();
+ // apply transmission mode gain
+ NS_LOG_DEBUG (this << " txMode " << (uint16_t)m_transmissionMode << " gain " << m_txModeGain.at (m_transmissionMode));
+ NS_ASSERT (m_transmissionMode < m_txModeGain.size ());
+ if (m_transmissionMode>0)
+ {
+ // in case of MIMO, ctrl is always txed as TX diversity
+ m_sinrPerceived *= m_txModeGain.at (1);
+ }
+// m_sinrPerceived *= m_txModeGain.at (m_transmissionMode);
+ bool error = false;
+ if (m_ctrlErrorModelEnabled)
+ {
+ double errorRate = LteMiErrorModel::GetPcfichPdcchError (m_sinrPerceived);
+ errorRate = LteMiErrorModel::GetPcfichPdcchError (m_sinrPerceived);
+ error = m_random.GetValue () > errorRate ? false : true;
+ NS_LOG_DEBUG (this << " PCFICH-PDCCH Decodification, errorRate " << errorRate << " error " << error);
+ }
+
+ if (!error)
+ {
+ if (!m_ltePhyRxCtrlEndOkCallback.IsNull ())
+ {
+ m_ltePhyRxCtrlEndOkCallback (m_rxControlMessageList);
+ }
+ }
+ else
+ {
+ if (!m_ltePhyRxCtrlEndErrorCallback.IsNull ())
+ {
+ m_ltePhyRxCtrlEndErrorCallback ();
+ }
+ }
+ ChangeState (IDLE);
+ m_rxControlMessageList.clear ();
+}
+
+void
+LteSpectrumPhy::EndRxUlSrs ()
+{
+ NS_ASSERT (m_state == RX_CTRL);
+ ChangeState (IDLE);
+ m_interferenceCtrl->EndRx ();
+ // nothing to do (used only for SRS at this stage)
+}
+
void
LteSpectrumPhy::SetCellId (uint16_t cellId)
{
m_cellId = cellId;
}
+
void
-LteSpectrumPhy::AddSinrChunkProcessor (Ptr<LteSinrChunkProcessor> p)
+LteSpectrumPhy::AddDataSinrChunkProcessor (Ptr<LteSinrChunkProcessor> p)
{
- m_interference->AddSinrChunkProcessor (p);
+ m_interferenceData->AddSinrChunkProcessor (p);
+}
+
+void
+LteSpectrumPhy::AddCtrlSinrChunkProcessor (Ptr<LteSinrChunkProcessor> p)
+{
+ m_interferenceCtrl->AddSinrChunkProcessor (p);
}
void
--- a/src/lte/model/lte-spectrum-phy.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-spectrum-phy.h Tue Jul 31 19:18:23 2012 +0200
@@ -38,6 +38,7 @@
#include <ns3/lte-interference.h>
#include <ns3/random-variable.h>
#include <map>
+#include <ns3/ff-mac-common.h>
namespace ns3 {
@@ -65,8 +66,54 @@
typedef std::map<TbId_t, tbInfo_t> expectedTbs_t;
+
class LteNetDevice;
class AntennaModel;
+class LteControlMessage;
+class LteSpectrumSignalParametersDataFrame;
+class LteSpectrumSignalParametersDlCtrlFrame;
+class LteSpectrumSignalParametersUlSrsFrame;
+
+
+/**
+* this method is invoked by the LteSpectrumPhy to notify the PHY that the
+* transmission of a given packet has been completed.
+*
+* @param packet the Packet whose TX has been completed.
+*/
+typedef Callback< void, Ptr<const Packet> > LtePhyTxEndCallback;
+
+/**
+* This method is used by the LteSpectrumPhy to notify the PHY that a
+* previously started RX attempt has terminated without success
+*/
+typedef Callback< void > LtePhyRxDataEndErrorCallback;
+/**
+* This method is used by the LteSpectrumPhy to notify the PHY that a
+* previously started RX attempt has been successfully completed.
+*
+* @param packet the received Packet
+*/
+typedef Callback< void, Ptr<Packet> > LtePhyRxDataEndOkCallback;
+
+
+/**
+* This method is used by the LteSpectrumPhy to notify the PHY that a
+* previously started RX of a control frame attempt has been
+* successfully completed.
+*
+* @param packet the received Packet
+*/
+typedef Callback< void, std::list<Ptr<LteControlMessage> > > LtePhyRxCtrlEndOkCallback;
+
+/**
+* This method is used by the LteSpectrumPhy to notify the PHY that a
+* previously started RX of a control frame attempt has terminated
+* without success.
+*/
+typedef Callback< void > LtePhyRxCtrlEndErrorCallback;
+
+
/**
* \ingroup lte
@@ -88,7 +135,7 @@
*/
enum State
{
- IDLE, TX, RX
+ IDLE, TX, RX_DATA, RX_CTRL
};
// inherited from Object
@@ -104,6 +151,8 @@
Ptr<const SpectrumModel> GetRxSpectrumModel () const;
Ptr<AntennaModel> GetRxAntenna ();
void StartRx (Ptr<SpectrumSignalParameters> params);
+ void StartRxData (Ptr<LteSpectrumSignalParametersDataFrame> params);
+ void StartRxCtrl (Ptr<SpectrumSignalParameters> params);
/**
* set the Power Spectral Density of outgoing signals in W/Hz.
@@ -125,17 +174,43 @@
* \param a the Antenna Model
*/
void SetAntenna (Ptr<AntennaModel> a);
-
+
+ /**
+ * Start a transmission of data frame in DL and UL
+ *
+ *
+ * @param pb the burst of packets to be transmitted in PDSCH/PUSCH
+ * @param ctrlMsgList the list of LteControlMessage to send
+ * @param duration the duration of the data frame
+ *
+ * @return true if an error occurred and the transmission was not
+ * started, false otherwise.
+ */
+ bool StartTxDataFrame (Ptr<PacketBurst> pb, std::list<Ptr<LteControlMessage> > ctrlMsgList, Time duration);
+
/**
- * Start a transmission
- *
- *
- * @param pb the burst of packets to be transmitted
- *
- * @return true if an error occurred and the transmission was not
- * started, false otherwise.
- */
- bool StartTx (Ptr<PacketBurst> pb);
+ * Start a transmission of control frame in DL
+ *
+ *
+ * @param dlDci the burst of DL-DCIs to be transmitted
+ * @param ulDci the burst of UL-DCIs to be transmitted
+ *
+ * @return true if an error occurred and the transmission was not
+ * started, false otherwise.
+ */
+ bool StartTxDlCtrlFrame (std::list<Ptr<LteControlMessage> > ctrlMsgList);
+
+
+ /**
+ * Start a transmission of control frame in UL
+ *
+ *
+ * @param pb the burst of control messages to be transmitted
+ *
+ * @return true if an error occurred and the transmission was not
+ * started, false otherwise.
+ */
+ bool StartTxUlSrsFrame ();
/**
@@ -144,7 +219,7 @@
*
* @param c the callback
*/
- void SetGenericPhyTxEndCallback (GenericPhyTxEndCallback c);
+ void SetLtePhyTxEndCallback (LtePhyTxEndCallback c);
/**
* set the callback for the end of a RX in error, as part of the
@@ -152,7 +227,7 @@
*
* @param c the callback
*/
- void SetGenericPhyRxEndErrorCallback (GenericPhyRxEndErrorCallback c);
+ void SetLtePhyRxDataEndErrorCallback (LtePhyRxDataEndErrorCallback c);
/**
* set the callback for the successful end of a RX, as part of the
@@ -160,7 +235,23 @@
*
* @param c the callback
*/
- void SetGenericPhyRxEndOkCallback (GenericPhyRxEndOkCallback c);
+ void SetLtePhyRxDataEndOkCallback (LtePhyRxDataEndOkCallback c);
+
+ /**
+ * set the callback for the successful end of a RX ctrl frame, as part
+ * of the interconnections betweenthe LteSpectrumPhy and the PHY
+ *
+ * @param c the callback
+ */
+ void SetLtePhyRxCtrlEndOkCallback (LtePhyRxCtrlEndOkCallback c);
+
+ /**
+ * set the callback for the erroneous end of a RX ctrl frame, as part
+ * of the interconnections betweenthe LteSpectrumPhy and the PHY
+ *
+ * @param c the callback
+ */
+ void SetLtePhyRxCtrlEndErrorCallback (LtePhyRxCtrlEndErrorCallback c);
/**
* \brief Set the state of the phy layer
@@ -177,11 +268,19 @@
/**
- *
- *
- * \param p the new LteSinrChunkProcessor to be added to the processing chain
- */
- void AddSinrChunkProcessor (Ptr<LteSinrChunkProcessor> p);
+ *
+ *
+ * \param p the new LteSinrChunkProcessor to be added to the data processing chain
+ */
+ void AddDataSinrChunkProcessor (Ptr<LteSinrChunkProcessor> p);
+
+
+ /**
+ *
+ *
+ * \param p the new LteSinrChunkProcessor to be added to the ctrl processing chain
+ */
+ void AddCtrlSinrChunkProcessor (Ptr<LteSinrChunkProcessor> p);
/**
*
@@ -214,7 +313,9 @@
private:
void ChangeState (State newState);
void EndTx ();
- void EndRx ();
+ void EndRxData ();
+ void EndRxDlCtrl ();
+ void EndRxUlSrs ();
void SetTxModeGain (uint8_t txMode, double gain);
@@ -229,7 +330,11 @@
Ptr<SpectrumValue> m_txPsd;
Ptr<PacketBurst> m_txPacketBurst;
std::list<Ptr<PacketBurst> > m_rxPacketBurstList;
-
+
+ std::list<Ptr<LteControlMessage> > m_txControlMessageList;
+ std::list<Ptr<LteControlMessage> > m_rxControlMessageList;
+
+
State m_state;
Time m_firstRxStart;
Time m_firstRxDuration;
@@ -240,11 +345,15 @@
TracedCallback<Ptr<const Packet> > m_phyRxEndOkTrace;
TracedCallback<Ptr<const Packet> > m_phyRxEndErrorTrace;
- GenericPhyTxEndCallback m_genericPhyTxEndCallback;
- GenericPhyRxEndErrorCallback m_genericPhyRxEndErrorCallback;
- GenericPhyRxEndOkCallback m_genericPhyRxEndOkCallback;
+ LtePhyTxEndCallback m_ltePhyTxEndCallback;
+ LtePhyRxDataEndErrorCallback m_ltePhyRxDataEndErrorCallback;
+ LtePhyRxDataEndOkCallback m_ltePhyRxDataEndOkCallback;
+
+ LtePhyRxCtrlEndOkCallback m_ltePhyRxCtrlEndOkCallback;
+ LtePhyRxCtrlEndErrorCallback m_ltePhyRxCtrlEndErrorCallback;
- Ptr<LteInterference> m_interference;
+ Ptr<LteInterference> m_interferenceData;
+ Ptr<LteInterference> m_interferenceCtrl;
uint16_t m_cellId;
@@ -252,7 +361,8 @@
SpectrumValue m_sinrPerceived;
UniformVariable m_random;
- bool m_pemEnabled; // when true (default) the phy error model is enabled
+ bool m_dataErrorModelEnabled; // when true (default) the phy error model is enabled
+ bool m_ctrlErrorModelEnabled; // when true (default) the phy error model is enabled for DL ctrl frame
uint8_t m_transmissionMode; // for UEs: store the transmission mode
std::vector <double> m_txModeGain; // duplicate value of LteUePhy
--- a/src/lte/model/lte-spectrum-signal-parameters.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-spectrum-signal-parameters.cc Tue Jul 31 19:18:23 2012 +0200
@@ -16,12 +16,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Nicola Baldo <nbaldo@cttc.es>
+ * Modified by Marco Miozzo <mmiozzo@cttc.es> (add data and ctrl diversity)
*/
#include <ns3/log.h>
#include <ns3/packet-burst.h>
#include <ns3/ptr.h>
-#include "lte-spectrum-signal-parameters.h"
+#include <ns3/lte-spectrum-signal-parameters.h>
+#include <ns3/lte-control-messages.h>
NS_LOG_COMPONENT_DEFINE ("LteSpectrumSignalParameters");
@@ -54,4 +56,99 @@
return lssp;
}
+
+
+LteSpectrumSignalParametersDataFrame::LteSpectrumSignalParametersDataFrame ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+LteSpectrumSignalParametersDataFrame::LteSpectrumSignalParametersDataFrame (const LteSpectrumSignalParametersDataFrame& p)
+: SpectrumSignalParameters (p)
+{
+ NS_LOG_FUNCTION (this << &p);
+ cellId = p.cellId;
+ if (p.packetBurst)
+ {
+ packetBurst = p.packetBurst->Copy ();
+ }
+ ctrlMsgList = p.ctrlMsgList;
+}
+
+Ptr<SpectrumSignalParameters>
+LteSpectrumSignalParametersDataFrame::Copy ()
+{
+ NS_LOG_FUNCTION (this);
+ // Ideally we would use:
+ // return Copy<LteSpectrumSignalParametersDataFrame> (*this);
+ // but for some reason it doesn't work. Another alternative is
+ // return Copy<LteSpectrumSignalParametersDataFrame> (this);
+ // but it causes a double creation of the object, hence it is less efficient.
+ // The solution below is copied from the implementation of Copy<> (Ptr<>) in ptr.h
+ Ptr<LteSpectrumSignalParametersDataFrame> lssp (new LteSpectrumSignalParametersDataFrame (*this), false);
+ return lssp;
+}
+
+
+
+LteSpectrumSignalParametersDlCtrlFrame::LteSpectrumSignalParametersDlCtrlFrame ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+LteSpectrumSignalParametersDlCtrlFrame::LteSpectrumSignalParametersDlCtrlFrame (const LteSpectrumSignalParametersDlCtrlFrame& p)
+: SpectrumSignalParameters (p)
+{
+ NS_LOG_FUNCTION (this << &p);
+ cellId = p.cellId;
+ ctrlMsgList = p.ctrlMsgList;
+}
+
+Ptr<SpectrumSignalParameters>
+LteSpectrumSignalParametersDlCtrlFrame::Copy ()
+{
+ NS_LOG_FUNCTION (this);
+ // Ideally we would use:
+ // return Copy<LteSpectrumSignalParametersDlCtrlFrame> (*this);
+ // but for some reason it doesn't work. Another alternative is
+ // return Copy<LteSpectrumSignalParametersDlCtrlFrame> (this);
+ // but it causes a double creation of the object, hence it is less efficient.
+ // The solution below is copied from the implementation of Copy<> (Ptr<>) in ptr.h
+ Ptr<LteSpectrumSignalParametersDlCtrlFrame> lssp (new LteSpectrumSignalParametersDlCtrlFrame (*this), false);
+ return lssp;
+}
+
+
+LteSpectrumSignalParametersUlSrsFrame::LteSpectrumSignalParametersUlSrsFrame ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+LteSpectrumSignalParametersUlSrsFrame::LteSpectrumSignalParametersUlSrsFrame (const LteSpectrumSignalParametersUlSrsFrame& p)
+: SpectrumSignalParameters (p)
+{
+ NS_LOG_FUNCTION (this << &p);
+ cellId = p.cellId;
+}
+
+Ptr<SpectrumSignalParameters>
+LteSpectrumSignalParametersUlSrsFrame::Copy ()
+{
+ NS_LOG_FUNCTION (this);
+ // Ideally we would use:
+ // return Copy<LteSpectrumSignalParametersUlSrsFrame> (*this);
+ // but for some reason it doesn't work. Another alternative is
+ // return Copy<LteSpectrumSignalParametersUlSrsFrame> (this);
+ // but it causes a double creation of the object, hence it is less efficient.
+ // The solution below is copied from the implementation of Copy<> (Ptr<>) in ptr.h
+ Ptr<LteSpectrumSignalParametersUlSrsFrame> lssp (new LteSpectrumSignalParametersUlSrsFrame (*this), false);
+ return lssp;
+}
+
+
+
+
+
+
+
} // namespace ns3
--- a/src/lte/model/lte-spectrum-signal-parameters.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-spectrum-signal-parameters.h Tue Jul 31 19:18:23 2012 +0200
@@ -16,6 +16,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Nicola Baldo <nbaldo@cttc.es>
+ * Modified by Marco Miozzo <mmiozzo@cttc.es> (add data and ctrl diversity)
*/
#ifndef LTE_SPECTRUM_SIGNAL_PARAMETERS_H
@@ -27,6 +28,8 @@
namespace ns3 {
class PacketBurst;
+class LteControlMessage;
+
/**
* \ingroup lte
@@ -55,6 +58,95 @@
Ptr<PacketBurst> packetBurst;
};
+
+/**
+* \ingroup lte
+*
+* Signal parameters for Lte Data Frame (PDSCH), and eventually after some
+* control messages through other control channel embedded in PDSCH
+* (i.e. PBCH)
+*/
+struct LteSpectrumSignalParametersDataFrame : public SpectrumSignalParameters
+{
+
+ // inherited from SpectrumSignalParameters
+ virtual Ptr<SpectrumSignalParameters> Copy ();
+
+ /**
+ * default constructor
+ */
+ LteSpectrumSignalParametersDataFrame ();
+
+ /**
+ * copy constructor
+ */
+ LteSpectrumSignalParametersDataFrame (const LteSpectrumSignalParametersDataFrame& p);
+
+ /**
+ * The packet burst being transmitted with this signal
+ */
+ Ptr<PacketBurst> packetBurst;
+
+ std::list<Ptr<LteControlMessage> > ctrlMsgList;
+
+ uint16_t cellId;
+};
+
+
+/**
+* \ingroup lte
+*
+* Signal parameters for Lte DL Ctrl Frame (RS, PCFICH and PDCCH)
+*/
+struct LteSpectrumSignalParametersDlCtrlFrame : public SpectrumSignalParameters
+{
+
+ // inherited from SpectrumSignalParameters
+ virtual Ptr<SpectrumSignalParameters> Copy ();
+
+ /**
+ * default constructor
+ */
+ LteSpectrumSignalParametersDlCtrlFrame ();
+
+ /**
+ * copy constructor
+ */
+ LteSpectrumSignalParametersDlCtrlFrame (const LteSpectrumSignalParametersDlCtrlFrame& p);
+
+
+ std::list<Ptr<LteControlMessage> > ctrlMsgList;
+
+ uint16_t cellId;
+};
+
+
+
+/**
+* \ingroup lte
+*
+* Signal parameters for Lte SRS Frame
+*/
+struct LteSpectrumSignalParametersUlSrsFrame : public SpectrumSignalParameters
+{
+
+ // inherited from SpectrumSignalParameters
+ virtual Ptr<SpectrumSignalParameters> Copy ();
+
+ /**
+ * default constructor
+ */
+ LteSpectrumSignalParametersUlSrsFrame ();
+
+ /**
+ * copy constructor
+ */
+ LteSpectrumSignalParametersUlSrsFrame (const LteSpectrumSignalParametersUlSrsFrame& p);
+
+ uint16_t cellId;
+};
+
+
} // namespace ns3
--- a/src/lte/model/lte-ue-cphy-sap.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-ue-cphy-sap.h Tue Jul 31 19:18:23 2012 +0200
@@ -77,6 +77,11 @@
*/
virtual void SetTransmissionMode (uint8_t txMode) = 0;
+ /**
+ * \param txMode the transmissionMode of the user
+ */
+ virtual void SetSrsConfigurationIndex (uint16_t srcCi) = 0;
+
};
@@ -116,6 +121,7 @@
virtual void SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth);
virtual void SetRnti (uint16_t rnti);
virtual void SetTransmissionMode (uint8_t txMode);
+ virtual void SetSrsConfigurationIndex (uint16_t srcCi);
private:
MemberLteUeCphySapProvider ();
@@ -168,6 +174,12 @@
m_owner->DoSetTransmissionMode (txMode);
}
+template <class C>
+void
+MemberLteUeCphySapProvider<C>::SetSrsConfigurationIndex (uint16_t srcCi)
+{
+ m_owner->DoSetSrsConfigurationIndex (srcCi);
+}
--- a/src/lte/model/lte-ue-mac.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-ue-mac.cc Tue Jul 31 19:18:23 2012 +0200
@@ -30,7 +30,7 @@
#include "lte-ue-net-device.h"
#include "lte-radio-bearer-tag.h"
#include <ns3/ff-mac-common.h>
-#include <ns3/ideal-control-messages.h>
+#include <ns3/lte-control-messages.h>
#include <ns3/simulator.h>
#include <ns3/lte-common.h>
@@ -128,7 +128,7 @@
// inherited from LtePhySapUser
virtual void ReceivePhyPdu (Ptr<Packet> p);
virtual void SubframeIndication (uint32_t frameNo, uint32_t subframeNo);
- virtual void ReceiveIdealControlMessage (Ptr<IdealControlMessage> msg);
+ virtual void ReceiveLteControlMessage (Ptr<LteControlMessage> msg);
private:
LteUeMac* m_mac;
@@ -153,9 +153,9 @@
}
void
-UeMemberLteUePhySapUser::ReceiveIdealControlMessage (Ptr<IdealControlMessage> msg)
+UeMemberLteUePhySapUser::ReceiveLteControlMessage (Ptr<LteControlMessage> msg)
{
- m_mac->DoReceiveIdealControlMessage (msg);
+ m_mac->DoReceiveLteControlMessage (msg);
}
@@ -302,9 +302,9 @@
bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (0));
// create the feedback to eNB
- Ptr<BsrIdealControlMessage> msg = Create<BsrIdealControlMessage> ();
+ Ptr<BsrLteControlMessage> msg = Create<BsrLteControlMessage> ();
msg->SetBsr (bsr);
- m_uePhySapProvider->SendIdealControlMessage (msg);
+ m_uePhySapProvider->SendLteControlMessage (msg);
}
@@ -331,7 +331,6 @@
m_macSapUserMap.erase (lcId);
}
-
void
LteUeMac::DoReceivePhyPdu (Ptr<Packet> p)
{
@@ -348,12 +347,12 @@
void
-LteUeMac::DoReceiveIdealControlMessage (Ptr<IdealControlMessage> msg)
+LteUeMac::DoReceiveLteControlMessage (Ptr<LteControlMessage> msg)
{
NS_LOG_FUNCTION (this);
- if (msg->GetMessageType () == IdealControlMessage::UL_DCI)
+ if (msg->GetMessageType () == LteControlMessage::UL_DCI)
{
- Ptr<UlDciIdealControlMessage> msg2 = DynamicCast<UlDciIdealControlMessage> (msg);
+ Ptr<UlDciLteControlMessage> msg2 = DynamicCast<UlDciLteControlMessage> (msg);
UlDciListElement_s dci = msg2->GetDci ();
std::map <uint8_t, uint64_t>::iterator itBsr;
NS_ASSERT_MSG (m_ulBsrReceived.size () <=4, " Too many LCs (max is 4)");
@@ -393,7 +392,7 @@
}
else
{
- NS_LOG_FUNCTION (this << " IdealControlMessage not recognized");
+ NS_LOG_FUNCTION (this << " LteControlMessage not recognized");
}
}
--- a/src/lte/model/lte-ue-mac.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-ue-mac.h Tue Jul 31 19:18:23 2012 +0200
@@ -85,7 +85,7 @@
// forwarded from PHY SAP
void DoReceivePhyPdu (Ptr<Packet> p);
- void DoReceiveIdealControlMessage (Ptr<IdealControlMessage> msg);
+ void DoReceiveLteControlMessage (Ptr<LteControlMessage> msg);
void SendReportBufferStatus (void);
--- a/src/lte/model/lte-ue-phy-sap.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-ue-phy-sap.h Tue Jul 31 19:18:23 2012 +0200
@@ -27,7 +27,7 @@
namespace ns3 {
-class IdealControlMessage;
+class LteControlMessage;
/**
* Service Access Point (SAP) offered by the UE-PHY to the UE-MAC
@@ -48,10 +48,10 @@
virtual void SendMacPdu (Ptr<Packet> p) = 0;
/**
- * \brief Send SendIdealControlMessage (PDCCH map, CQI feedbacks) using the ideal control channel
+ * \brief Send SendLteControlMessage (PDCCH map, CQI feedbacks) using the ideal control channel
* \param msg the Ideal Control Message to send
*/
- virtual void SendIdealControlMessage (Ptr<IdealControlMessage> msg) = 0;
+ virtual void SendLteControlMessage (Ptr<LteControlMessage> msg) = 0;
};
@@ -84,10 +84,10 @@
virtual void SubframeIndication (uint32_t frameNo, uint32_t subframeNo) = 0;
/**
- * \brief Receive SendIdealControlMessage (PDCCH map, CQI feedbacks) using the ideal control channel
+ * \brief Receive SendLteControlMessage (PDCCH map, CQI feedbacks) using the ideal control channel
* \param msg the Ideal Control Message to receive
*/
- virtual void ReceiveIdealControlMessage (Ptr<IdealControlMessage> msg) = 0;
+ virtual void ReceiveLteControlMessage (Ptr<LteControlMessage> msg) = 0;
};
--- a/src/lte/model/lte-ue-phy.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-ue-phy.cc Tue Jul 31 19:18:23 2012 +0200
@@ -42,6 +42,22 @@
namespace ns3 {
+
+
+
+// duration of data portion of UL subframe
+// = TTI - 1 symbol for SRS - 1ns as margin to avoid overlapping simulator events
+// (symbol duration in nanoseconds = TTI / 14 (rounded))
+// in other words, duration of data portion of UL subframe = TTI*(13/14) -1ns
+static const Time UL_DATA_DURATION = NanoSeconds (1e6 - 71429 - 1);
+
+// delay from subframe start to transmission of SRS
+// = TTI - 1 symbol for SRS
+static const Time UL_SRS_DELAY_FROM_SUBFRAME_START = NanoSeconds (1e6 - 71429);
+
+
+
+
////////////////////////////////////////
// member SAP forwarders
////////////////////////////////////////
@@ -54,7 +70,8 @@
// inherited from LtePhySapProvider
virtual void SendMacPdu (Ptr<Packet> p);
- virtual void SendIdealControlMessage (Ptr<IdealControlMessage> msg);
+ virtual void SendLteControlMessage (Ptr<LteControlMessage> msg);
+ virtual void SetSrsConfigurationIndex (uint16_t srcCi);
private:
LteUePhy* m_phy;
@@ -73,11 +90,16 @@
}
void
-UeMemberLteUePhySapProvider::SendIdealControlMessage (Ptr<IdealControlMessage> msg)
+UeMemberLteUePhySapProvider::SendLteControlMessage (Ptr<LteControlMessage> msg)
{
- m_phy->DoSendIdealControlMessage (msg);
+ m_phy->DoSendLteControlMessage (msg);
}
+void
+UeMemberLteUePhySapProvider::SetSrsConfigurationIndex (uint16_t srcCi)
+{
+ m_phy->DoSetSrsConfigurationIndex (srcCi);
+}
////////////////////////////////////////
@@ -103,21 +125,25 @@
// ideal behavior
m_a30CqiLast (MilliSeconds (0)),
m_uePhySapUser (0),
- m_ueCphySapUser (0)
+ m_ueCphySapUser (0),
+ m_rnti (0),
+ m_srsPeriodicity (0)
{
m_amc = CreateObject <LteAmc> ();
m_uePhySapProvider = new UeMemberLteUePhySapProvider (this);
m_ueCphySapProvider = new MemberLteUeCphySapProvider<LteUePhy> (this);
- m_macChTtiDelay = UL_PUSCH_TTIS_DELAY + 1; // +1 for avoiding UL/DL trigger synchronization remove 1 TTI of delay
+ m_macChTtiDelay = UL_PUSCH_TTIS_DELAY;
for (int i = 0; i < m_macChTtiDelay; i++)
{
Ptr<PacketBurst> pb = CreateObject <PacketBurst> ();
m_packetBurstQueue.push_back (pb);
- std::list<Ptr<IdealControlMessage> > l;
+ std::list<Ptr<LteControlMessage> > l;
m_controlMessagesQueue.push_back (l);
}
std::vector <int> ulRb;
m_subChannelsForTransmissionQueue.resize (m_macChTtiDelay, ulRb);
+
+ Simulator::ScheduleNow (&LteUePhy::SubframeIndication, this, 1, 1);
}
@@ -287,19 +313,6 @@
}
void
-LteUePhy::DoSetUplinkSubChannels ()
-{
- NS_LOG_FUNCTION (this);
-
- /*
- * XXX: the uplink scheduler is not implemented yet!
- * Now, all uplink sub channels can be used for uplink transmission
- */
- SetSubChannelsForTransmission (GetUplinkSubChannels ());
-}
-
-
-void
LteUePhy::SetSubChannelsForTransmission (std::vector <int> mask)
{
NS_LOG_FUNCTION (this);
@@ -346,30 +359,36 @@
}
void
-LteUePhy::GenerateCqiReport (const SpectrumValue& sinr)
+LteUePhy::GenerateCtrlCqiReport (const SpectrumValue& sinr)
{
NS_LOG_FUNCTION (this);
// check periodic wideband CQI
if (Simulator::Now () > m_p10CqiLast + m_p10CqiPeriocity)
{
Ptr<LteUeNetDevice> thisDevice = GetDevice ()->GetObject<LteUeNetDevice> ();
- Ptr<DlCqiIdealControlMessage> msg = CreateDlCqiFeedbackMessage (sinr);
- DoSendIdealControlMessage (msg);
+ Ptr<DlCqiLteControlMessage> msg = CreateDlCqiFeedbackMessage (sinr);
+ DoSendLteControlMessage (msg);
m_p10CqiLast = Simulator::Now ();
}
// check aperiodic high-layer configured subband CQI
if (Simulator::Now () > m_a30CqiLast + m_a30CqiPeriocity)
{
Ptr<LteUeNetDevice> thisDevice = GetDevice ()->GetObject<LteUeNetDevice> ();
- Ptr<DlCqiIdealControlMessage> msg = CreateDlCqiFeedbackMessage (sinr);
- DoSendIdealControlMessage (msg);
+ Ptr<DlCqiLteControlMessage> msg = CreateDlCqiFeedbackMessage (sinr);
+ DoSendLteControlMessage (msg);
m_a30CqiLast = Simulator::Now ();
}
}
+void
+LteUePhy::GenerateDataCqiReport (const SpectrumValue& sinr)
+{
+ // Not used by UE, CQI are based only on RS
+}
-Ptr<DlCqiIdealControlMessage>
+
+Ptr<DlCqiLteControlMessage>
LteUePhy::CreateDlCqiFeedbackMessage (const SpectrumValue& sinr)
{
NS_LOG_FUNCTION (this);
@@ -382,8 +401,8 @@
- // CREATE DlCqiIdealControlMessage
- Ptr<DlCqiIdealControlMessage> msg = Create<DlCqiIdealControlMessage> ();
+ // CREATE DlCqiLteControlMessage
+ Ptr<DlCqiLteControlMessage> msg = Create<DlCqiLteControlMessage> ();
CqiListElement_s dlcqi;
std::vector<int> cqi;
if (Simulator::Now () > m_p10CqiLast + m_p10CqiPeriocity)
@@ -473,86 +492,102 @@
void
-LteUePhy::DoSendIdealControlMessage (Ptr<IdealControlMessage> msg)
+LteUePhy::DoSendLteControlMessage (Ptr<LteControlMessage> msg)
{
NS_LOG_FUNCTION (this << msg);
- Ptr<LteUeNetDevice> thisDevice = GetDevice ()->GetObject<LteUeNetDevice> ();
- msg->SetSourceDevice (thisDevice);
- msg->SetDestinationDevice (m_enbDevice);
+
SetControlMessages (msg);
}
void
-LteUePhy::ReceiveIdealControlMessage (Ptr<IdealControlMessage> msg)
+LteUePhy::ReceiveLteControlMessageList (std::list<Ptr<LteControlMessage> > msgList)
{
- NS_LOG_FUNCTION (this << msg);
-
- if (msg->GetMessageType () == IdealControlMessage::DL_DCI)
+ NS_LOG_FUNCTION (this);
+
+ std::list<Ptr<LteControlMessage> >::iterator it;
+ for (it = msgList.begin (); it != msgList.end(); it++)
+ {
+ Ptr<LteControlMessage> msg = (*it);
+
+ if (msg->GetMessageType () == LteControlMessage::DL_DCI)
{
- Ptr<DlDciIdealControlMessage> msg2 = DynamicCast<DlDciIdealControlMessage> (msg);
-
+ Ptr<DlDciLteControlMessage> msg2 = DynamicCast<DlDciLteControlMessage> (msg);
+
DlDciListElement_s dci = msg2->GetDci ();
-
- if (dci.m_resAlloc != 0)
+ if (dci.m_rnti != m_rnti)
{
- NS_FATAL_ERROR ("Resource Allocation type not implemented");
+ // DCI not for me
+ continue;
}
-
+
+ if (dci.m_resAlloc != 0)
+ {
+ NS_FATAL_ERROR ("Resource Allocation type not implemented");
+ }
+
std::vector <int> dlRb;
-
+
// translate the DCI to Spectrum framework
uint32_t mask = 0x1;
for (int i = 0; i < 32; i++)
+ {
+ if (((dci.m_rbBitmap & mask) >> i) == 1)
{
- if (((dci.m_rbBitmap & mask) >> i) == 1)
- {
- for (int k = 0; k < GetRbgSize (); k++)
- {
- dlRb.push_back ((i * GetRbgSize ()) + k);
- //NS_LOG_DEBUG(this << "DL-DCI allocated PRB " << (i*GetRbgSize()) + k);
- }
- }
- mask = (mask << 1);
+ for (int k = 0; k < GetRbgSize (); k++)
+ {
+ dlRb.push_back ((i * GetRbgSize ()) + k);
+ //NS_LOG_DEBUG(this << "DL-DCI allocated PRB " << (i*GetRbgSize()) + k);
+ }
}
+ mask = (mask << 1);
+ }
// send TB info to LteSpectrumPhy
- NS_LOG_DEBUG (this << " UE " << m_rnti << " DCI " << dci.m_rnti << " bitmap " << dci.m_rbBitmap);
+ NS_LOG_DEBUG (this << " UE " << m_rnti << " DL-DCI " << dci.m_rnti << " bitmap " << dci.m_rbBitmap);
for (uint8_t i = 0; i < dci.m_tbsSize.size (); i++)
- {
- m_downlinkSpectrumPhy->AddExpectedTb (dci.m_rnti, dci.m_tbsSize.at (i), dci.m_mcs.at (i), dlRb, i);
- }
-
+ {
+ m_downlinkSpectrumPhy->AddExpectedTb (dci.m_rnti, dci.m_tbsSize.at (i), dci.m_mcs.at (i), dlRb, i);
+ }
+
SetSubChannelsForReception (dlRb);
-
-
+
+
}
- else if (msg->GetMessageType () == IdealControlMessage::UL_DCI)
+ else if (msg->GetMessageType () == LteControlMessage::UL_DCI)
{
// set the uplink bandwidht according to the UL-CQI
NS_LOG_DEBUG (this << " UL DCI");
- Ptr<UlDciIdealControlMessage> msg2 = DynamicCast<UlDciIdealControlMessage> (msg);
+ Ptr<UlDciLteControlMessage> msg2 = DynamicCast<UlDciLteControlMessage> (msg);
UlDciListElement_s dci = msg2->GetDci ();
+ if (dci.m_rnti != m_rnti)
+ {
+ // DCI not for me
+ continue;
+ }
std::vector <int> ulRb;
for (int i = 0; i < dci.m_rbLen; i++)
- {
- ulRb.push_back (i + dci.m_rbStart);
- //NS_LOG_DEBUG (this << " UE RB " << i + dci.m_rbStart);
- }
-
+ {
+ ulRb.push_back (i + dci.m_rbStart);
+ //NS_LOG_DEBUG (this << " UE RB " << i + dci.m_rbStart);
+ }
+
QueueSubChannelsForTransmission (ulRb);
// pass the info to the MAC
- m_uePhySapUser->ReceiveIdealControlMessage (msg);
+ m_uePhySapUser->ReceiveLteControlMessage (msg);
}
- else
+ else
{
// pass the message to UE-MAC
- m_uePhySapUser->ReceiveIdealControlMessage (msg);
+ m_uePhySapUser->ReceiveLteControlMessage (msg);
}
+
+ }
+
+
+}
-}
-
void
LteUePhy::QueueSubChannelsForTransmission (std::vector <int> rbMap)
{
@@ -564,7 +599,6 @@
LteUePhy::SubframeIndication (uint32_t frameNo, uint32_t subframeNo)
{
NS_LOG_FUNCTION (this << frameNo << subframeNo);
- // trigger from eNB
// update uplink transmission mask according to previous UL-CQIs
SetSubChannelsForTransmission (m_subChannelsForTransmissionQueue.at (0));
@@ -575,37 +609,81 @@
}
m_subChannelsForTransmissionQueue.at (m_macChTtiDelay-1).clear ();
-
- // send control messages
- std::list<Ptr<IdealControlMessage> > ctrlMsg = GetControlMessages ();
- if (ctrlMsg.size () > 0)
+ bool srs = false;
+ // check SRS periodicity
+ if (m_srsCounter==1)
{
- Ptr<LtePhy> phy = m_enbDevice->GetPhy ();
- std::list<Ptr<IdealControlMessage> >::iterator it;
- it = ctrlMsg.begin ();
- while (it != ctrlMsg.end ())
- {
- Ptr<IdealControlMessage> msg = (*it);
- phy->ReceiveIdealControlMessage (msg);
- ctrlMsg.pop_front ();
- it = ctrlMsg.begin ();
- }
+ srs = true;
+ m_srsCounter = m_srsPeriodicity;
+ }
+ else
+ {
+ m_srsCounter--;
}
+ if (srs)
+ {
+ Simulator::Schedule (UL_SRS_DELAY_FROM_SUBFRAME_START,
+ &LteUePhy::SendSrs,
+ this);
+ }
+
+
+ std::list<Ptr<LteControlMessage> > ctrlMsg = GetControlMessages ();
// send packets in queue
// send the current burts of packets
Ptr<PacketBurst> pb = GetPacketBurst ();
if (pb)
{
- NS_LOG_LOGIC (this << " UE - start TX");
- m_uplinkSpectrumPhy->StartTx (pb);
+ NS_LOG_LOGIC (this << " UE - start TX PUSCH + PUCCH");
+ m_uplinkSpectrumPhy->StartTxDataFrame (pb, ctrlMsg, UL_DATA_DURATION);
}
+ else
+ {
+ // send only PUCCH (ideal: fake full bandwidth signal)
+ if (ctrlMsg.size ()>0)
+ {
+ std::vector <int> dlRb;
+ for (uint8_t i = 0; i < m_ulBandwidth; i++)
+ {
+ dlRb.push_back (i);
+ }
+ SetSubChannelsForTransmission (dlRb);
+ m_uplinkSpectrumPhy->StartTxDataFrame (pb, ctrlMsg, UL_DATA_DURATION);
+ }
+ }
+
// trigger the MAC
m_uePhySapUser->SubframeIndication (frameNo, subframeNo);
+
+ ++subframeNo;
+ if (subframeNo > 10)
+ {
+ ++frameNo;
+ subframeNo = 1;
+ }
+
+ // schedule next subframe indication
+ Simulator::Schedule (Seconds (GetTti ()), &LteUePhy::SubframeIndication, this, frameNo, subframeNo);
}
+void
+LteUePhy::SendSrs ()
+{
+ NS_LOG_FUNCTION (this << " UE " << m_rnti << " start tx SRS, cell Id " << m_cellId);
+ // set the current tx power spectral density (full bandwidth)
+ std::vector <int> dlRb;
+ for (uint8_t i = 0; i < m_ulBandwidth; i++)
+ {
+ dlRb.push_back (i);
+ }
+ SetSubChannelsForTransmission (dlRb);
+ m_uplinkSpectrumPhy->StartTxUlSrsFrame ();
+}
+
+
void
LteUePhy::DoSetRnti (uint16_t rnti)
@@ -666,6 +744,15 @@
m_downlinkSpectrumPhy->SetTransmissionMode (txMode);
}
+void
+LteUePhy::DoSetSrsConfigurationIndex (uint16_t srcCi)
+{
+ NS_LOG_FUNCTION (this << srcCi);
+ m_srsPeriodicity = GetSrsPeriodicity (srcCi);
+ m_srsCounter = GetSrsSubframeOffset (srcCi) + 1;
+ NS_LOG_DEBUG (this << " UE SRS P " << m_srsPeriodicity << " RNTI " << m_rnti << " offset " << GetSrsSubframeOffset (srcCi) << " cellId " << m_cellId << " CI " << srcCi);
+}
+
void
LteUePhy::SetTxMode1Gain (double gain)
--- a/src/lte/model/lte-ue-phy.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-ue-phy.h Tue Jul 31 19:18:23 2012 +0200
@@ -26,7 +26,7 @@
#include <ns3/lte-phy.h>
#include <ns3/ff-mac-common.h>
-#include <ns3/ideal-control-messages.h>
+#include <ns3/lte-control-messages.h>
#include <ns3/lte-amc.h>
#include <ns3/lte-ue-phy-sap.h>
#include <ns3/lte-ue-cphy-sap.h>
@@ -133,11 +133,6 @@
virtual Ptr<SpectrumValue> CreateTxPowerSpectralDensity ();
/**
- * \brief Update available channel for TX
- */
- virtual void DoSetUplinkSubChannels ();
-
- /**
* \brief Set a list of sub channels to use in TX
* \param mask a list of sub channels
*/
@@ -165,16 +160,18 @@
* the physical layer with the signal received from eNB
* \param sinr SINR values vector
*/
- Ptr<DlCqiIdealControlMessage> CreateDlCqiFeedbackMessage (const SpectrumValue& sinr);
+ Ptr<DlCqiLteControlMessage> CreateDlCqiFeedbackMessage (const SpectrumValue& sinr);
// inherited from LtePhy
- virtual void GenerateCqiReport (const SpectrumValue& sinr);
+ virtual void GenerateCtrlCqiReport (const SpectrumValue& sinr);
+ virtual void GenerateDataCqiReport (const SpectrumValue& sinr);
- virtual void DoSendIdealControlMessage (Ptr<IdealControlMessage> msg);
- virtual void ReceiveIdealControlMessage (Ptr<IdealControlMessage> msg);
+ virtual void DoSendLteControlMessage (Ptr<LteControlMessage> msg);
+ virtual void ReceiveLteControlMessageList (std::list<Ptr<LteControlMessage> >);
+ virtual void DoSetSrsConfigurationIndex (uint16_t srcCi);
@@ -194,6 +191,12 @@
void SubframeIndication (uint32_t frameNo, uint32_t subframeNo);
+ /**
+ * \brief Send the SRS signal in the last symbols of the frame
+ */
+ void SendSrs ();
+
+
private:
@@ -247,6 +250,9 @@
uint8_t m_transmissionMode;
std::vector <double> m_txModeGain;
+
+ uint16_t m_srsPeriodicity;
+ uint16_t m_srsCounter;
};
--- a/src/lte/model/lte-ue-rrc.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-ue-rrc.cc Tue Jul 31 19:18:23 2012 +0200
@@ -291,7 +291,7 @@
{
NS_LOG_FUNCTION (this);
- m_rnti = m_enbRrc->ConnectionRequest (m_imsi);
+ m_rnti = m_enbRrc->DoRecvConnectionRequest (m_imsi);
m_cmacSapProvider->ConfigureUe (m_rnti);
m_cphySapProvider->SetRnti (m_rnti);
}
@@ -321,16 +321,28 @@
return v;
}
+void
+LteUeRrc::DoRecvConnectionSetup (LteUeConfig_t params)
+{
+ m_cphySapProvider->SetTransmissionMode (params.m_transmissionMode);
+ m_cphySapProvider->SetSrsConfigurationIndex (params.m_srsConfigurationIndex);
+
+
+ m_enbRrc->DoRecvConnectionSetupCompleted (m_rnti);
+}
+
void
-LteUeRrc::DoRrcConfigurationUpdateInd (LteUeConfig_t params)
+LteUeRrc::DoRecvConnectionReconfiguration (LteUeConfig_t params)
{
NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
m_cphySapProvider->SetTransmissionMode (params.m_transmissionMode);
+ m_cphySapProvider->SetSrsConfigurationIndex (params.m_srsConfigurationIndex);
+
}
void
-LteUeRrc::ConnectionReconfigurationWithMobilityControlInfo (uint16_t targetCellId, uint16_t newRnti)
+LteUeRrc::DoRecvConnectionReconfigurationWithMobilityControlInfo (uint16_t targetCellId, uint16_t newRnti)
{
Ptr<LteEnbNetDevice> enbDev;
// WILD HACK - eventually we'll get rid of all these Ptr<Device> around
@@ -357,13 +369,13 @@
}
}
NS_ASSERT_MSG (found , " Unable to find eNB with CellId =" << targetCellId);
-
+ m_enbRrc = enbDev->GetObject<LteEnbRrc> ();
DoForceCampedOnEnb (enbDev, targetCellId);
m_rnti = newRnti;
m_cmacSapProvider->ConfigureUe (m_rnti);
m_cphySapProvider->SetRnti (m_rnti);
- enbDev->GetObject<LteEnbRrc> ()->ConnectionReestablishmentRequest (m_imsi, m_rnti);
+ m_enbRrc->DoRecvConnectionReconfigurationCompleted (m_rnti);
}
--- a/src/lte/model/lte-ue-rrc.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/lte-ue-rrc.h Tue Jul 31 19:18:23 2012 +0200
@@ -179,12 +179,18 @@
*/
std::vector<uint8_t> GetLcIdVector ();
+
/**
- * message from eNB-RRC for changing UE's configuration
- * (up to now TxMode)
- *
- */
- void DoRrcConfigurationUpdateInd (LteUeConfig_t params);
+ * reception of the RRC ConnectionReconfiguration message
+ *
+ */
+ void DoRecvConnectionSetup (LteUeConfig_t params);
+
+ /**
+ * reception of the RRC ConnectionReconfiguration message
+ *
+ */
+ void DoRecvConnectionReconfiguration (LteUeConfig_t params);
/**
@@ -193,7 +199,7 @@
* \param targetCellId
* \param newRnti
*/
- void ConnectionReconfigurationWithMobilityControlInfo (uint16_t targetCellId, uint16_t newRnti);
+ void DoRecvConnectionReconfigurationWithMobilityControlInfo (uint16_t targetCellId, uint16_t newRnti);
private:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-vendor-specific-parameters.cc Tue Jul 31 19:18:23 2012 +0200
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * 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: Marco Miozzo <marco.miozzo@cttc.es>
+ */
+
+#include <ns3/lte-vendor-specific-parameters.h>
+#include <ns3/log.h>
+
+NS_LOG_COMPONENT_DEFINE ("LteVendorSpecificParameters");
+
+namespace ns3 {
+
+SrsCqiRntiVsp::SrsCqiRntiVsp (uint16_t rnti)
+: m_rnti (rnti)
+{
+
+}
+
+SrsCqiRntiVsp::~SrsCqiRntiVsp ()
+{
+
+}
+
+uint16_t
+SrsCqiRntiVsp::GetRnti ()
+{
+ return (m_rnti);
+}
+
+
+}; // namespace ns3
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-vendor-specific-parameters.h Tue Jul 31 19:18:23 2012 +0200
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * 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: Marco Miozzo <marco.miozzo@cttc.es>
+ */
+
+#ifndef LTE_VENDOR_SPECIFIC_PARAMETERS
+#define LTE_VENDOR_SPECIFIC_PARAMETERS
+
+#include <ns3/ff-mac-common.h>
+
+
+#define SRS_CQI_RNTI_VSP 1
+
+
+namespace ns3 {
+
+/**
+* \brief Define the RNTI that has generated the
+*/
+class SrsCqiRntiVsp : public VendorSpecificValue
+{
+ public:
+ SrsCqiRntiVsp (uint16_t rnti);
+ virtual ~SrsCqiRntiVsp ();
+
+ uint16_t GetRnti ();
+
+ private:
+ uint16_t m_rnti;
+};
+
+
+
+}; // namespace ns3
+
+#endif /* LTE_VENDOR_SPECIFIC_PARAMETERS */
+
--- a/src/lte/model/pf-ff-mac-scheduler.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/pf-ff-mac-scheduler.cc Tue Jul 31 19:18:23 2012 +0200
@@ -28,6 +28,7 @@
#include <ns3/simulator.h>
#include <ns3/lte-amc.h>
#include <ns3/pf-ff-mac-scheduler.h>
+#include <ns3/lte-vendor-specific-parameters.h>
NS_LOG_COMPONENT_DEFINE ("PfFfMacScheduler");
@@ -294,14 +295,13 @@
NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
std::map <uint16_t,uint8_t>::iterator it = m_uesTxMode.find (params.m_rnti);
if (it==m_uesTxMode.end ())
- {
- m_uesTxMode.insert (std::pair <uint16_t, double> (params.m_rnti, params.m_transmissionMode));
- }
+ {
+ m_uesTxMode.insert (std::pair <uint16_t, double> (params.m_rnti, params.m_transmissionMode));
+ }
else
- {
- (*it).second = params.m_transmissionMode;
- }
- return;
+ {
+ (*it).second = params.m_transmissionMode;
+ }
return;
}
@@ -934,7 +934,7 @@
rbgAllocationMap.push_back ((*it).first);
}
uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8);
-// NS_LOG_DEBUG (this << " UE " << (*it).first << " startPRB " << (uint32_t)uldci.m_rbStart << " nPRB " << (uint32_t)uldci.m_rbLen << " CQI " << cqi << " MCS " << (uint32_t)uldci.m_mcs << " TBsize " << uldci.m_tbSize << " RbAlloc " << rbAllocated);
+ NS_LOG_DEBUG (this << " UE " << (*it).first << " startPRB " << (uint32_t)uldci.m_rbStart << " nPRB " << (uint32_t)uldci.m_rbLen << " CQI " << cqi << " MCS " << (uint32_t)uldci.m_mcs << " TBsize " << uldci.m_tbSize << " RbAlloc " << rbAllocated);
UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
uldci.m_ndi = 1;
uldci.m_cceIndex = 0;
@@ -1053,57 +1053,147 @@
NS_LOG_FUNCTION (this);
// NS_LOG_DEBUG (this << " RX SFNID " << params.m_sfnSf);
// retrieve the allocation for this subframe
- std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
- std::map <uint16_t, std::vector <double> >::iterator itCqi;
- itMap = m_allocationMaps.find (params.m_sfnSf);
- if (itMap == m_allocationMaps.end ())
- {
- NS_LOG_DEBUG (this << " Does not find info on allocation, size : " << m_allocationMaps.size ());
- return;
- }
- for (uint32_t i = 0; i < (*itMap).second.size (); i++)
+ switch (m_ulCqiFilter)
{
- // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
-// NS_LOG_INFO (this << " i " << i << " size " << params.m_ulCqi.m_sinr.size () << " mapSIze " << (*itMap).second.size ());
- double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
- //NS_LOG_DEBUG (this << " UE " << (*itMap).second.at (i) << " SINRfp " << params.m_ulCqi.m_sinr.at (i) << " sinrdb " << sinr);
- itCqi = m_ueCqi.find ((*itMap).second.at (i));
- if (itCqi == m_ueCqi.end ())
+ case FfMacScheduler::SRS_UL_CQI:
+ {
+ // filter all the CQIs that are not SRS based
+ if (params.m_ulCqi.m_type!=UlCqi_s::SRS)
+ {
+ return;
+ }
+ }
+ break;
+ case FfMacScheduler::PUSCH_UL_CQI:
{
- // create a new entry
- std::vector <double> newCqi;
+ // filter all the CQIs that are not SRS based
+ if (params.m_ulCqi.m_type!=UlCqi_s::PUSCH)
+ {
+ return;
+ }
+ }
+ case FfMacScheduler::ALL_UL_CQI:
+ break;
+
+ default:
+ NS_FATAL_ERROR ("Unknown UL CQI type");
+ }
+
+ switch (params.m_ulCqi.m_type)
+ {
+ case UlCqi_s::PUSCH:
+ {
+ std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
+ std::map <uint16_t, std::vector <double> >::iterator itCqi;
+ itMap = m_allocationMaps.find (params.m_sfnSf);
+ if (itMap == m_allocationMaps.end ())
+ {
+ NS_LOG_DEBUG (this << " Does not find info on allocation, size : " << m_allocationMaps.size ());
+ return;
+ }
+ for (uint32_t i = 0; i < (*itMap).second.size (); i++)
+ {
+ // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
+ // NS_LOG_INFO (this << " i " << i << " size " << params.m_ulCqi.m_sinr.size () << " mapSIze " << (*itMap).second.size ());
+ double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
+ //NS_LOG_DEBUG (this << " UE " << (*itMap).second.at (i) << " SINRfp " << params.m_ulCqi.m_sinr.at (i) << " sinrdb " << sinr);
+ itCqi = m_ueCqi.find ((*itMap).second.at (i));
+ if (itCqi == m_ueCqi.end ())
+ {
+ // create a new entry
+ std::vector <double> newCqi;
+ for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
+ {
+ if (i == j)
+ {
+ newCqi.push_back (sinr);
+ }
+ else
+ {
+ // initialize with NO_SINR value.
+ newCqi.push_back (NO_SINR);
+ }
+
+ }
+ m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
+ // generate correspondent timer
+ m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
+ }
+ else
+ {
+ // update the value
+ (*itCqi).second.at (i) = sinr;
+ // update correspondent timer
+ std::map <uint16_t, uint32_t>::iterator itTimers;
+ itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
+ (*itTimers).second = m_cqiTimersThreshold;
+
+ }
+
+ }
+ // remove obsolete info on allocation
+ m_allocationMaps.erase (itMap);
+ }
+ break;
+ case UlCqi_s::SRS:
+ {
+ // get the RNTI from vendor specific parameters
+ uint16_t rnti;
+ NS_ASSERT (params.m_vendorSpecificList.size () > 0);
+ for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
+ {
+ if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
+ {
+ Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
+ rnti = vsp->GetRnti ();
+ }
+ }
+ std::map <uint16_t, std::vector <double> >::iterator itCqi;
+ itCqi = m_ueCqi.find (rnti);
+ if (itCqi == m_ueCqi.end ())
+ {
+ // create a new entry
+ std::vector <double> newCqi;
+ for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
+ {
+ double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
+ newCqi.push_back (sinr);
+ NS_LOG_DEBUG (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
+
+ }
+ m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
+ // generate correspondent timer
+ m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
+ }
+ else
+ {
+ // update the values
for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
{
- if (i == j)
- {
- newCqi.push_back (sinr);
- }
- else
- {
- // initialize with NO_SINR value.
- newCqi.push_back (NO_SINR);
- }
-
+ double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
+ (*itCqi).second.at (j) = sinr;
+ NS_LOG_DEBUG (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
}
- m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
- // generate correspondent timer
- m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
- }
- else
- {
- // update the value
- (*itCqi).second.at (i) = sinr;
// update correspondent timer
std::map <uint16_t, uint32_t>::iterator itTimers;
- itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
+ itTimers = m_ueCqiTimers.find (rnti);
(*itTimers).second = m_cqiTimersThreshold;
}
-
- }
- // remove obsolete info on allocation
- m_allocationMaps.erase (itMap);
-
+
+
+ }
+ break;
+ case UlCqi_s::PUCCH_1:
+ case UlCqi_s::PUCCH_2:
+ case UlCqi_s::PRACH:
+ {
+ NS_FATAL_ERROR ("PfFfMacScheduler supports only PUSCH and SRS UL-CQIs");
+ }
+ break;
+ default:
+ NS_FATAL_ERROR ("Unknown type of UL-CQI");
+ }
return;
}
--- a/src/lte/model/rem-spectrum-phy.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/rem-spectrum-phy.cc Tue Jul 31 19:18:23 2012 +0200
@@ -16,6 +16,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Nicola Baldo <nbaldo@cttc.es>
+ * Modified by: Marco Miozzo <mmiozzo@cttc.es> convert to
+ * LteSpectrumSignalParametersDlCtrlFrame framework
*/
@@ -24,6 +26,7 @@
#include <ns3/double.h>
#include <ns3/simulator.h>
#include <ns3/trace-source-accessor.h>
+#include <ns3/lte-spectrum-signal-parameters.h>
#include <ns3/antenna-model.h>
#include "rem-spectrum-phy.h"
@@ -119,15 +122,19 @@
RemSpectrumPhy::StartRx (Ptr<SpectrumSignalParameters> params)
{
NS_LOG_FUNCTION ( this << params);
+
if (m_active)
- {
- double power = Integral (*(params->psd));
- NS_ASSERT_MSG (params->duration.GetMilliSeconds () == 1,
- "RemSpectrumPhy works only for LTE signals with duration of 1 ms");
- m_sumPower += power;
- if (power > m_referenceSignalPower)
+ {
+ Ptr<LteSpectrumSignalParametersDlCtrlFrame> lteDlCtrlRxParams = DynamicCast<LteSpectrumSignalParametersDlCtrlFrame> (params);
+ if (lteDlCtrlRxParams!=0)
{
- m_referenceSignalPower = power;
+ double power = Integral (*(params->psd));
+
+ m_sumPower += power;
+ if (power > m_referenceSignalPower)
+ {
+ m_referenceSignalPower = power;
+ }
}
}
}
--- a/src/lte/model/rr-ff-mac-scheduler.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/model/rr-ff-mac-scheduler.cc Tue Jul 31 19:18:23 2012 +0200
@@ -29,6 +29,7 @@
#include <ns3/rr-ff-mac-scheduler.h>
#include <ns3/simulator.h>
#include <ns3/lte-common.h>
+#include <ns3/lte-vendor-specific-parameters.h>
NS_LOG_COMPONENT_DEFINE ("RrFfMacScheduler");
@@ -539,7 +540,7 @@
// int totRbg = lcNum * rbgPerFlow;
// totRbg = rbgNum / nTbs;
int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (0), rbgPerTb * rbgSize) / 8);
- NS_LOG_DEBUG (this << "Allocate user " << newEl.m_rnti << " LCs " << (uint16_t)(*itLcRnti).second << " bytes " << tbSize << " PRBs " << rbgAllocated * rbgSize << "..." << (rbgAllocated* rbgSize) + (rbgPerTb * rbgSize) - 1 << " mcs " << (uint16_t) newDci.m_mcs.at (0) << " layers " << nLayer);
+ NS_LOG_DEBUG (this << " DL - Allocate user " << newEl.m_rnti << " LCs " << (uint16_t)(*itLcRnti).second << " bytes " << tbSize << " PRBs " << rbgAllocated * rbgSize << "..." << (rbgAllocated* rbgSize) + (rbgPerTb * rbgSize) - 1 << " mcs " << (uint16_t) newDci.m_mcs.at (0) << " layers " << nLayer);
uint16_t rlcPduSize = tbSize / lcNum;
for (int i = 0; i < lcNum ; i++)
{
@@ -855,56 +856,146 @@
NS_LOG_FUNCTION (this);
NS_LOG_DEBUG (this << " RX SFNID " << params.m_sfnSf);
// NS_LOG_DEBUG (this << " Actual sfn " << frameNo << " sbfn " << subframeNo << " sfnSf " << sfnSf);
- // retrieve the allocation for this subframe
- std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
- std::map <uint16_t, std::vector <double> >::iterator itCqi;
- itMap = m_allocationMaps.find (params.m_sfnSf);
- if (itMap == m_allocationMaps.end ())
+ switch (m_ulCqiFilter)
{
- NS_LOG_DEBUG (this << " Does not find info on allocation");
- return;
+ case FfMacScheduler::SRS_UL_CQI:
+ {
+ // filter all the CQIs that are not SRS based
+ if (params.m_ulCqi.m_type!=UlCqi_s::SRS)
+ {
+ return;
+ }
+ }
+ break;
+ case FfMacScheduler::PUSCH_UL_CQI:
+ {
+ // filter all the CQIs that are not SRS based
+ if (params.m_ulCqi.m_type!=UlCqi_s::PUSCH)
+ {
+ return;
+ }
+ }
+ case FfMacScheduler::ALL_UL_CQI:
+ break;
+
+ default:
+ NS_FATAL_ERROR ("Unknown UL CQI type");
}
- for (uint32_t i = 0; i < (*itMap).second.size (); i++)
+ switch (params.m_ulCqi.m_type)
{
- // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
- double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
-// NS_LOG_DEBUG (this << " RB " << i << "UE " << (*itMap).second.at (i) << " SINRfp " << params.m_ulCqi.m_sinr.at (i) << " sinrdb " << sinr);
- itCqi = m_ueCqi.find ((*itMap).second.at (i));
- if (itCqi == m_ueCqi.end ())
+ case UlCqi_s::PUSCH:
{
- // create a new entry
- std::vector <double> newCqi;
- for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
+ std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
+ std::map <uint16_t, std::vector <double> >::iterator itCqi;
+ itMap = m_allocationMaps.find (params.m_sfnSf);
+ if (itMap == m_allocationMaps.end ())
+ {
+ NS_LOG_DEBUG (this << " Does not find info on allocation, size : " << m_allocationMaps.size ());
+ return;
+ }
+ for (uint32_t i = 0; i < (*itMap).second.size (); i++)
{
- if (i == j)
+ // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
+ // NS_LOG_INFO (this << " i " << i << " size " << params.m_ulCqi.m_sinr.size () << " mapSIze " << (*itMap).second.size ());
+ double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
+ //NS_LOG_DEBUG (this << " UE " << (*itMap).second.at (i) << " SINRfp " << params.m_ulCqi.m_sinr.at (i) << " sinrdb " << sinr);
+ itCqi = m_ueCqi.find ((*itMap).second.at (i));
+ if (itCqi == m_ueCqi.end ())
{
- newCqi.push_back (sinr);
+ // create a new entry
+ std::vector <double> newCqi;
+ for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
+ {
+ if (i == j)
+ {
+ newCqi.push_back (sinr);
+ }
+ else
+ {
+ // initialize with NO_SINR value.
+ newCqi.push_back (30.0);
+ }
+
+ }
+ m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
+ // generate correspondent timer
+ m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
}
else
{
- // initialize with maximum value according to the fixed point notation
- newCqi.push_back (30.0);
+ // update the value
+ (*itCqi).second.at (i) = sinr;
+ // update correspondent timer
+ std::map <uint16_t, uint32_t>::iterator itTimers;
+ itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
+ (*itTimers).second = m_cqiTimersThreshold;
+
}
-
+
}
- m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
- // generate correspondent timer
- m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
+ // remove obsolete info on allocation
+ m_allocationMaps.erase (itMap);
}
- else
+ break;
+ case UlCqi_s::SRS:
{
- // update the value
- (*itCqi).second.at (i) = sinr;
- // update correspondent timer
- std::map <uint16_t, uint32_t>::iterator itTimers;
- itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
- (*itTimers).second = m_cqiTimersThreshold;
+ // get the RNTI from vendor specific parameters
+ uint16_t rnti;
+ NS_ASSERT (params.m_vendorSpecificList.size () > 0);
+ for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
+ {
+ if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
+ {
+ Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
+ rnti = vsp->GetRnti ();
+ }
+ }
+ std::map <uint16_t, std::vector <double> >::iterator itCqi;
+ itCqi = m_ueCqi.find (rnti);
+ if (itCqi == m_ueCqi.end ())
+ {
+ // create a new entry
+ std::vector <double> newCqi;
+ for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
+ {
+ double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
+ newCqi.push_back (sinr);
+ NS_LOG_DEBUG (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
+
+ }
+ m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
+ // generate correspondent timer
+ m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
+ }
+ else
+ {
+ // update the values
+ for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
+ {
+ double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
+ (*itCqi).second.at (j) = sinr;
+ NS_LOG_DEBUG (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
+ }
+ // update correspondent timer
+ std::map <uint16_t, uint32_t>::iterator itTimers;
+ itTimers = m_ueCqiTimers.find (rnti);
+ (*itTimers).second = m_cqiTimersThreshold;
+
+ }
+
+
}
-
+ break;
+ case UlCqi_s::PUCCH_1:
+ case UlCqi_s::PUCCH_2:
+ case UlCqi_s::PRACH:
+ {
+ NS_FATAL_ERROR ("PfFfMacScheduler supports only PUSCH and SRS UL-CQIs");
+ }
+ break;
+ default:
+ NS_FATAL_ERROR ("Unknown type of UL-CQI");
}
- // remove obsolete info on allocation
- m_allocationMaps.erase (itMap);
-
return;
}
--- a/src/lte/test/lte-test-downlink-sinr.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/lte-test-downlink-sinr.cc Tue Jul 31 19:18:23 2012 +0200
@@ -16,6 +16,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Manuel Requena <manuel.requena@cttc.es>
+ * Modified by Marco Miozzo <mmiozzo@ctt.es>
+ * Extend to Data and Ctrl frames
*/
#include "ns3/simulator.h"
@@ -23,14 +25,15 @@
#include "ns3/log.h"
#include "ns3/spectrum-test.h"
-
+#include "ns3/boolean.h"
#include "ns3/lte-phy-tag.h"
-#include "ns3/lte-sinr-chunk-processor.h"
+#include "ns3/lte-test-ue-phy.h"
+#include "ns3/lte-test-sinr-chunk-processor.h"
#include "ns3/lte-spectrum-signal-parameters.h"
#include "lte-test-downlink-sinr.h"
-#include "lte-test-ue-phy.h"
-
+#include <ns3/lte-control-messages.h>
+#include "ns3/lte-helper.h"
NS_LOG_COMPONENT_DEFINE ("LteDownlinkSinrTest");
@@ -79,7 +82,8 @@
(*theoreticalSinr1)[0] = 3.72589167251055;
(*theoreticalSinr1)[1] = 3.72255684126076;
- AddTestCase (new LteDownlinkSinrTestCase (rxPsd1, theoreticalSinr1, "sdBm = [-46 -48]"));
+ AddTestCase (new LteDownlinkDataSinrTestCase (rxPsd1, theoreticalSinr1, "sdBm = [-46 -48]"));
+ AddTestCase (new LteDownlinkCtrlSinrTestCase (rxPsd1, theoreticalSinr1, "sdBm = [-46 -48]"));
/**
* TX signal #2: Power Spectral Density (W/Hz) of the signal of interest = [-63 -61] dBm and BW = [20 22] MHz
@@ -92,7 +96,9 @@
(*theoreticalSinr2)[0] = 0.0743413124381667;
(*theoreticalSinr2)[1] = 0.1865697965291756;
- AddTestCase (new LteDownlinkSinrTestCase (rxPsd2, theoreticalSinr2, "sdBm = [-63 -61]"));
+ AddTestCase (new LteDownlinkDataSinrTestCase (rxPsd2, theoreticalSinr2, "sdBm = [-63 -61]"));
+ AddTestCase (new LteDownlinkCtrlSinrTestCase (rxPsd2, theoreticalSinr2, "sdBm = [-63 -61]"));
+
}
@@ -100,11 +106,11 @@
/**
- * TestCase
+ * TestCase Data
*/
-LteDownlinkSinrTestCase::LteDownlinkSinrTestCase (Ptr<SpectrumValue> sv, Ptr<SpectrumValue> sinr, std::string name)
- : TestCase ("SINR calculation in downlink: " + name),
+LteDownlinkDataSinrTestCase::LteDownlinkDataSinrTestCase (Ptr<SpectrumValue> sv, Ptr<SpectrumValue> sinr, std::string name)
+ : TestCase ("SINR calculation in downlink Data frame: " + name),
m_sv (sv),
m_sm (sv->GetSpectrumModel ()),
m_sinr (sinr)
@@ -112,30 +118,33 @@
NS_LOG_INFO ("Creating LenaDownlinkSinrTestCase");
}
-LteDownlinkSinrTestCase::~LteDownlinkSinrTestCase ()
+LteDownlinkDataSinrTestCase::~LteDownlinkDataSinrTestCase ()
{
}
void
-LteDownlinkSinrTestCase::DoRun (void)
+LteDownlinkDataSinrTestCase::DoRun (void)
{
+ Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
/**
* Instantiate a single receiving LteSpectrumPhy
*/
Ptr<LteSpectrumPhy> dlPhy = CreateObject<LteSpectrumPhy> ();
Ptr<LteSpectrumPhy> ulPhy = CreateObject<LteSpectrumPhy> ();
Ptr<LteTestUePhy> uePhy = CreateObject<LteTestUePhy> (dlPhy, ulPhy);
-
- dlPhy->SetCellId (100);
+ uint16_t cellId = 100;
+ dlPhy->SetCellId (cellId);
+ ulPhy->SetCellId (cellId);
- Ptr<LteCqiSinrChunkProcessor> chunkProcessor = Create<LteCqiSinrChunkProcessor> (uePhy->GetObject<LtePhy> ());
- dlPhy->AddSinrChunkProcessor (chunkProcessor);
+ Ptr<LteTestSinrChunkProcessor> chunkProcessor = Create<LteTestSinrChunkProcessor> (uePhy->GetObject<LtePhy> ());
+ dlPhy->AddDataSinrChunkProcessor (chunkProcessor);
/**
- * Generate several calls to LteSpectrumPhy::StartRx corresponding to several signals.
- * One will be the signal of interest, i.e., the PhyTag of the first Packet in the Packet burst
- * will have the same CellId of the receiving PHY;
- * the others will have a different CellId and hence will be the interfering signals
+ * Generate several calls to LteSpectrumPhy::StartRx corresponding to
+ * several signals. One will be the signal of interest, i.e., the
+ * LteSpectrumSignalParametersDataFrame of the Packet burst
+ * will have the same CellId of the receiving PHY; the others will have
+ * a different CellId and hence will be the interfering signals
*/
// Number of packet bursts (1 data + 4 interferences)
@@ -149,9 +158,9 @@
// Packets
Ptr<Packet> pkt[numOfPbs][numOfPkts];
-
- // Phy tags
- LtePhyTag pktTag[numOfPbs];
+
+ // Packet bursts cellId
+ uint16_t pbCellId[numOfPbs];
/**
* Build packet burst
@@ -160,20 +169,13 @@
{
// Create packet burst
packetBursts[pb] = CreateObject<PacketBurst> ();
+ pbCellId[pb] = cellId * (pb + 1);
// Create packets and add them to the burst
for ( int i = 0 ; i < numOfPkts ; i++ )
{
pkt[pb][i] = Create<Packet> (1000);
- if ( i == 0 )
- {
- // Create phy tag (different for each packet burst)
- // and add to the first packet
- pktTag[pb] = LtePhyTag (100 * (pb + 1));
- pkt[pb][i]->AddPacketTag ( pktTag[pb] );
- }
-
packetBursts[pb]->AddPacket ( pkt[pb][i] );
}
}
@@ -215,40 +217,45 @@
*/
// eNB sends data to 2 UEs through 2 subcarriers
- Ptr<LteSpectrumSignalParameters> sp1 = Create<LteSpectrumSignalParameters> ();
+ Ptr<LteSpectrumSignalParametersDataFrame> sp1 = Create<LteSpectrumSignalParametersDataFrame> ();
sp1->psd = m_sv;
sp1->txPhy = 0;
sp1->duration = ds;
sp1->packetBurst = packetBursts[0];
+ sp1->cellId = pbCellId[0];
Simulator::Schedule (ts, &LteSpectrumPhy::StartRx, dlPhy, sp1);
- Ptr<LteSpectrumSignalParameters> ip1 = Create<LteSpectrumSignalParameters> ();
+ Ptr<LteSpectrumSignalParametersDataFrame> ip1 = Create<LteSpectrumSignalParametersDataFrame> ();
ip1->psd = i1;
ip1->txPhy = 0;
ip1->duration = di1;
ip1->packetBurst = packetBursts[1];
+ ip1->cellId = pbCellId[1];
Simulator::Schedule (ti1, &LteSpectrumPhy::StartRx, dlPhy, ip1);
- Ptr<LteSpectrumSignalParameters> ip2 = Create<LteSpectrumSignalParameters> ();
+ Ptr<LteSpectrumSignalParametersDataFrame> ip2 = Create<LteSpectrumSignalParametersDataFrame> ();
ip2->psd = i2;
ip2->txPhy = 0;
ip2->duration = di2;
ip2->packetBurst = packetBursts[2];
+ ip2->cellId = pbCellId[2];
Simulator::Schedule (ti2, &LteSpectrumPhy::StartRx, dlPhy, ip2);
- Ptr<LteSpectrumSignalParameters> ip3 = Create<LteSpectrumSignalParameters> ();
+ Ptr<LteSpectrumSignalParametersDataFrame> ip3 = Create<LteSpectrumSignalParametersDataFrame> ();
ip3->psd = i3;
ip3->txPhy = 0;
ip3->duration = di3;
ip3->packetBurst = packetBursts[3];
+ ip3->cellId = pbCellId[3];
Simulator::Schedule (ti3, &LteSpectrumPhy::StartRx, dlPhy, ip3);
- Ptr<LteSpectrumSignalParameters> ip4 = Create<LteSpectrumSignalParameters> ();
+ Ptr<LteSpectrumSignalParametersDataFrame> ip4 = Create<LteSpectrumSignalParametersDataFrame> ();
ip4->psd = i4;
ip4->txPhy = 0;
ip4->duration = di4;
ip4->packetBurst = packetBursts[4];
+ ip4->cellId = pbCellId[4];
Simulator::Schedule (ti4, &LteSpectrumPhy::StartRx, dlPhy, ip4);
Simulator::Stop (Seconds (5.0));
@@ -258,15 +265,182 @@
* Check that the values passed to LteSinrChunkProcessor::EvaluateSinrChunk () correspond
* to known values which have been calculated offline (with octave) for the generated signals
*/
- SpectrumValue calculatedSinr = uePhy->GetSinr ();
+ Ptr<SpectrumValue> calculatedSinr = chunkProcessor->GetSinr ();
- NS_LOG_INFO ("Theoretical SINR: " << *m_sinr);
- NS_LOG_INFO ("Calculated SINR: " << calculatedSinr);
+ NS_LOG_INFO ("Data Frame - Theoretical SINR: " << *m_sinr);
+ NS_LOG_INFO ("Data Frame - Calculated SINR: " << *calculatedSinr);
- NS_TEST_ASSERT_MSG_SPECTRUM_VALUE_EQ_TOL(calculatedSinr, *m_sinr, 0.0000001, "Wrong SINR !");
+ NS_TEST_ASSERT_MSG_SPECTRUM_VALUE_EQ_TOL(*calculatedSinr, *m_sinr, 0.0000001, "Data Frame - Wrong SINR !");
dlPhy->Dispose ();
Simulator::Destroy ();
}
-} // namespace ns3
+
+
+/**
+* TestCase CTRL
+*/
+
+LteDownlinkCtrlSinrTestCase::LteDownlinkCtrlSinrTestCase (Ptr<SpectrumValue> sv, Ptr<SpectrumValue> sinr, std::string name)
+: TestCase ("SINR calculation in downlink Ctrl Frame: " + name),
+m_sv (sv),
+m_sm (sv->GetSpectrumModel ()),
+m_sinr (sinr)
+{
+ NS_LOG_INFO ("Creating LenaDownlinkCtrlSinrTestCase");
+}
+
+LteDownlinkCtrlSinrTestCase::~LteDownlinkCtrlSinrTestCase ()
+{
+}
+void
+LteDownlinkCtrlSinrTestCase::DoRun (void)
+{
+ /**
+ * Instantiate a single receiving LteSpectrumPhy
+ */
+ Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+ Ptr<LteSpectrumPhy> dlPhy = CreateObject<LteSpectrumPhy> ();
+ Ptr<LteSpectrumPhy> ulPhy = CreateObject<LteSpectrumPhy> ();
+ Ptr<LteTestUePhy> uePhy = CreateObject<LteTestUePhy> (dlPhy, ulPhy);
+ uint16_t cellId = 100;
+ dlPhy->SetCellId (cellId);
+ ulPhy->SetCellId (cellId);
+
+ Ptr<LteTestSinrChunkProcessor> chunkProcessor = Create<LteTestSinrChunkProcessor> (uePhy->GetObject<LtePhy> ());
+ dlPhy->AddCtrlSinrChunkProcessor (chunkProcessor);
+
+ /**
+ * Generate several calls to LteSpectrumPhy::StartRx corresponding to several signals. One will be the signal of interest, i.e., the
+ * LteSpectrumSignalParametersDlCtrlFrame of the first signal will have the
+ * same CellId of the receiving PHY; the others will have a different
+ * CellId and hence will be the interfering signals
+ */
+
+ // Number of ctrl bursts (1 data + 4 interferences)
+ int numOfUes = 5;
+
+ // Number of control messages in the list
+ int numOfCtrlMsgs = 10;
+
+ // control messages in the list
+ std::list<Ptr<LteControlMessage> > ctrlMsgList[numOfUes];
+
+ // signals cellId
+ uint16_t pbCellId[numOfUes];
+
+ /**
+ * Build ctrl msg lists
+ */
+ for ( int pb = 0 ; pb < numOfUes ; pb++ )
+ {
+ pbCellId[pb] = cellId * (pb + 1);
+
+ // Create ctrl msg and add them to the list
+ for ( int i = 0 ; i < numOfCtrlMsgs ; i++ )
+ {
+ Ptr<DlDciLteControlMessage> msg = Create<DlDciLteControlMessage> ();
+ DlDciListElement_s dci;
+ msg->SetDci (dci);
+ ctrlMsgList[pb].push_back (msg);
+ }
+ }
+
+
+ Ptr<SpectrumValue> noisePsd = Create<SpectrumValue> (m_sm);
+ Ptr<SpectrumValue> i1 = Create<SpectrumValue> (m_sm);
+ Ptr<SpectrumValue> i2 = Create<SpectrumValue> (m_sm);
+ Ptr<SpectrumValue> i3 = Create<SpectrumValue> (m_sm);
+ Ptr<SpectrumValue> i4 = Create<SpectrumValue> (m_sm);
+
+ (*noisePsd)[0] = 5.000000000000e-19;
+ (*noisePsd)[1] = 4.545454545455e-19;
+
+ (*i1)[0] = 5.000000000000e-18;
+ (*i2)[0] = 5.000000000000e-16;
+ (*i3)[0] = 1.581138830084e-16;
+ (*i4)[0] = 7.924465962306e-17;
+ (*i1)[1] = 1.437398936440e-18;
+ (*i2)[1] = 5.722388235428e-16;
+ (*i3)[1] = 7.204059965732e-17;
+ (*i4)[1] = 5.722388235428e-17;
+
+ Time ts = Seconds (1);
+ Time ds = Seconds (1);
+ Time ti1 = Seconds (0);
+ Time di1 = Seconds (3);
+ Time ti2 = Seconds (0.7);
+ Time di2 = Seconds (1);
+ Time ti3 = Seconds (1.2);
+ Time di3 = Seconds (1);
+ Time ti4 = Seconds (1.5);
+ Time di4 = Seconds (0.1);
+
+ dlPhy->SetNoisePowerSpectralDensity (noisePsd);
+
+ /**
+ * Schedule the reception of the data signal plus the interference signals
+ */
+
+ // eNB sends data to 2 UEs through 2 subcarriers
+ Ptr<LteSpectrumSignalParametersDlCtrlFrame> sp1 = Create<LteSpectrumSignalParametersDlCtrlFrame> ();
+ sp1->psd = m_sv;
+ sp1->txPhy = 0;
+ sp1->duration = ds;
+ sp1->ctrlMsgList = ctrlMsgList[0];
+ sp1->cellId = pbCellId[0];
+ Simulator::Schedule (ts, &LteSpectrumPhy::StartRx, dlPhy, sp1);
+
+
+ Ptr<LteSpectrumSignalParametersDlCtrlFrame> ip1 = Create<LteSpectrumSignalParametersDlCtrlFrame> ();
+ ip1->psd = i1;
+ ip1->txPhy = 0;
+ ip1->duration = di1;
+ ip1->ctrlMsgList = ctrlMsgList[1];
+ ip1->cellId = pbCellId[1];
+ Simulator::Schedule (ti1, &LteSpectrumPhy::StartRx, dlPhy, ip1);
+
+ Ptr<LteSpectrumSignalParametersDlCtrlFrame> ip2 = Create<LteSpectrumSignalParametersDlCtrlFrame> ();
+ ip2->psd = i2;
+ ip2->txPhy = 0;
+ ip2->duration = di2;
+ ip2->ctrlMsgList = ctrlMsgList[2];
+ ip2->cellId = pbCellId[2];
+ Simulator::Schedule (ti2, &LteSpectrumPhy::StartRx, dlPhy, ip2);
+
+ Ptr<LteSpectrumSignalParametersDlCtrlFrame> ip3 = Create<LteSpectrumSignalParametersDlCtrlFrame> ();
+ ip3->psd = i3;
+ ip3->txPhy = 0;
+ ip3->duration = di3;
+ ip3->ctrlMsgList = ctrlMsgList[3];
+ ip3->cellId = pbCellId[3];
+ Simulator::Schedule (ti3, &LteSpectrumPhy::StartRx, dlPhy, ip3);
+
+ Ptr<LteSpectrumSignalParametersDlCtrlFrame> ip4 = Create<LteSpectrumSignalParametersDlCtrlFrame> ();
+ ip4->psd = i4;
+ ip4->txPhy = 0;
+ ip4->duration = di4;
+ ip4->ctrlMsgList = ctrlMsgList[4];
+ ip4->cellId = pbCellId[4];
+ Simulator::Schedule (ti4, &LteSpectrumPhy::StartRx, dlPhy, ip4);
+
+ Simulator::Stop (Seconds (5.0));
+ Simulator::Run ();
+
+ /**
+ * Check that the values passed to LteSinrChunkProcessor::EvaluateSinrChunk () correspond
+ * to known values which have been calculated offline (with octave) for the generated signals
+ */
+ Ptr<SpectrumValue> calculatedSinr = chunkProcessor->GetSinr ();
+
+ NS_LOG_INFO ("Ctrl Frame - Theoretical SINR: " << *m_sinr);
+ NS_LOG_INFO ("Ctrl Frame - Calculated SINR: " << *calculatedSinr);
+
+ NS_TEST_ASSERT_MSG_SPECTRUM_VALUE_EQ_TOL(*calculatedSinr, *m_sinr, 0.0000001, "Data Frame - Wrong SINR !");
+ dlPhy->Dispose ();
+ Simulator::Destroy ();
+}
+
+
+} // namespace
\ No newline at end of file
--- a/src/lte/test/lte-test-downlink-sinr.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/lte-test-downlink-sinr.h Tue Jul 31 19:18:23 2012 +0200
@@ -16,6 +16,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Manuel Requena <manuel.requena@cttc.es>
+ * Modified by Marco Miozzo <mmiozzo@ctt.es>
+ * Extend to Data and Ctrl frames
*/
#ifndef LTE_TEST_DOWNLINK_SINR_H
@@ -39,11 +41,11 @@
};
-class LteDownlinkSinrTestCase : public TestCase
+class LteDownlinkDataSinrTestCase : public TestCase
{
public:
- LteDownlinkSinrTestCase (Ptr<SpectrumValue> sv, Ptr<SpectrumValue> sinr, std::string name);
- virtual ~LteDownlinkSinrTestCase ();
+ LteDownlinkDataSinrTestCase (Ptr<SpectrumValue> sv, Ptr<SpectrumValue> sinr, std::string name);
+ virtual ~LteDownlinkDataSinrTestCase ();
private:
virtual void DoRun (void);
@@ -54,6 +56,19 @@
};
+class LteDownlinkCtrlSinrTestCase : public TestCase
+{
+ public:
+ LteDownlinkCtrlSinrTestCase (Ptr<SpectrumValue> sv, Ptr<SpectrumValue> sinr, std::string name);
+ virtual ~LteDownlinkCtrlSinrTestCase ();
+
+ private:
+ virtual void DoRun (void);
+
+ Ptr<SpectrumValue> m_sv;
+ Ptr<const SpectrumModel> m_sm;
+ Ptr<SpectrumValue> m_sinr;
+};
} // namespace ns3
--- a/src/lte/test/lte-test-interference.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/lte-test-interference.cc Tue Jul 31 19:18:23 2012 +0200
@@ -24,9 +24,10 @@
#include "ns3/string.h"
#include "ns3/double.h"
#include <ns3/enum.h>
-
+#include "ns3/boolean.h"
#include "ns3/mobility-helper.h"
#include "ns3/lte-helper.h"
+#include "ns3/ff-mac-scheduler.h"
#include "ns3/lte-enb-phy.h"
#include "ns3/lte-enb-net-device.h"
@@ -113,6 +114,8 @@
void
LteInterferenceTestCase::DoRun (void)
{
+ Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+ Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
Config::SetDefault ("ns3::LteAmc::Ber", DoubleValue (0.00005));
Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
@@ -153,6 +156,7 @@
NetDeviceContainer ueDevs1;
NetDeviceContainer ueDevs2;
lteHelper->SetSchedulerType ("ns3::RrFfMacScheduler");
+ lteHelper->SetSchedulerAttribute ("UlCqiFilter", EnumValue (FfMacScheduler::PUSCH_UL_CQI));
enbDevs = lteHelper->InstallEnbDevice (enbNodes);
ueDevs1 = lteHelper->InstallUeDevice (ueNodes1);
ueDevs2 = lteHelper->InstallUeDevice (ueNodes2);
@@ -172,11 +176,11 @@
Ptr<LtePhy> ue1Phy = ueDevs1.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
Ptr<LteTestSinrChunkProcessor> testDlSinr1 = Create<LteTestSinrChunkProcessor> (ue1Phy);
- ue1Phy->GetDownlinkSpectrumPhy ()->AddSinrChunkProcessor (testDlSinr1);
+ ue1Phy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testDlSinr1);
Ptr<LtePhy> enb1phy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
Ptr<LteTestSinrChunkProcessor> testUlSinr1 = Create<LteTestSinrChunkProcessor> (enb1phy);
- enb1phy->GetUplinkSpectrumPhy ()->AddSinrChunkProcessor (testUlSinr1);
+ enb1phy->GetUplinkSpectrumPhy ()->AddDataSinrChunkProcessor (testUlSinr1);
Config::Connect ("/NodeList/0/DeviceList/0/LteEnbMac/DlScheduling",
MakeBoundCallback (&LteTestDlSchedulingCallback, this));
@@ -189,11 +193,11 @@
Ptr<LtePhy> ue2Phy = ueDevs2.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
Ptr<LteTestSinrChunkProcessor> testDlSinr2 = Create<LteTestSinrChunkProcessor> (ue2Phy);
- ue2Phy->GetDownlinkSpectrumPhy ()->AddSinrChunkProcessor (testDlSinr2);
+ ue2Phy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testDlSinr2);
Ptr<LtePhy> enb2phy = enbDevs.Get (1)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
Ptr<LteTestSinrChunkProcessor> testUlSinr2 = Create<LteTestSinrChunkProcessor> (enb2phy);
- enb1phy->GetUplinkSpectrumPhy ()->AddSinrChunkProcessor (testUlSinr2);
+ enb1phy->GetUplinkSpectrumPhy ()->AddDataSinrChunkProcessor (testUlSinr2);
Config::Connect ("/NodeList/1/DeviceList/0/LteEnbMac/DlScheduling",
MakeBoundCallback (&LteTestDlSchedulingCallback, this));
@@ -247,7 +251,7 @@
* For first 5 subframeNo in the first frameNo, the MCS cannot be properly evaluated,
* because CQI feedback is still not available at the eNB.
*/
- if ( (frameNo > 1) && (subframeNo > 4) )
+ if ( (frameNo > 1) && (subframeNo > 6) )
{
NS_TEST_ASSERT_MSG_EQ ((uint16_t)mcs, m_ulMcs, "Wrong UL MCS");
}
--- a/src/lte/test/lte-test-link-adaptation.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/lte-test-link-adaptation.cc Tue Jul 31 19:18:23 2012 +0200
@@ -201,7 +201,7 @@
// It will be used to test that the SNR is as intended
Ptr<LtePhy> uePhy = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
Ptr<LteTestSinrChunkProcessor> testSinr = Create<LteTestSinrChunkProcessor> (uePhy);
- uePhy->GetDownlinkSpectrumPhy ()->AddSinrChunkProcessor (testSinr);
+ uePhy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testSinr);
Config::Connect ("/NodeList/0/DeviceList/0/LteEnbMac/DlScheduling",
MakeBoundCallback (&LteTestDlSchedulingCallback, this));
--- a/src/lte/test/lte-test-mimo.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/lte-test-mimo.cc Tue Jul 31 19:18:23 2012 +0200
@@ -107,40 +107,6 @@
{
// Config::SetDefault ("ns3::LteSpectrumPhy::PemEnabled", BooleanValue (false));
Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
- LogComponentDisableAll (LOG_LEVEL_ALL);
-// LogComponentEnable ("LteEnbRrc", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteUeRrc", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteEnbMac", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteUeMac", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteRlc", LOG_LEVEL_ALL);
-//
-// LogComponentEnable ("LtePhy", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteEnbPhy", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteUePhy", LOG_LEVEL_ALL);
-
-// LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteInterference", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteSinrChunkProcessor", LOG_LEVEL_ALL);
-//
-// LogComponentEnable ("LtePropagationLossModel", LOG_LEVEL_ALL);
-// LogComponentEnable ("LossModel", LOG_LEVEL_ALL);
-// LogComponentEnable ("ShadowingLossModel", LOG_LEVEL_ALL);
-// LogComponentEnable ("PenetrationLossModel", LOG_LEVEL_ALL);
-// LogComponentEnable ("MultipathLossModel", LOG_LEVEL_ALL);
-// LogComponentEnable ("PathLossModel", LOG_LEVEL_ALL);
-//
-// LogComponentEnable ("LteNetDevice", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteUeNetDevice", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteEnbNetDevice", LOG_LEVEL_ALL);
-
-// LogComponentEnable ("LteMiErrorModel", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteAmc", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL);
-
- LogComponentEnable ("LenaTestMimo", LOG_LEVEL_ALL);
-// LogComponentEnable ("BuildingsPropagationLossModel", LOG_LEVEL_ALL);
-// LogComponentEnable ("RrFfMacScheduler", LOG_LEVEL_ALL);
-// LogComponentEnable ("PfFfMacScheduler", LOG_LEVEL_ALL);
/**
--- a/src/lte/test/lte-test-pathloss-model.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/lte-test-pathloss-model.cc Tue Jul 31 19:18:23 2012 +0200
@@ -272,7 +272,7 @@
// It will be used to test that the SNR is as intended
//Ptr<LtePhy> uePhy = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
Ptr<LteTestSinrChunkProcessor> testSinr = Create<LteTestSinrChunkProcessor> (uePhy);
- uePhy->GetDownlinkSpectrumPhy ()->AddSinrChunkProcessor (testSinr);
+ uePhy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testSinr);
// Config::Connect ("/NodeList/0/DeviceList/0/LteEnbMac/DlScheduling",
// MakeBoundCallback (&LteTestPathlossDlSchedCallback, this));
--- a/src/lte/test/lte-test-pf-ff-mac-scheduler.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/lte-test-pf-ff-mac-scheduler.cc Tue Jul 31 19:18:23 2012 +0200
@@ -209,8 +209,8 @@
{
Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
Config::SetDefault ("ns3::LteAmc::Ber", DoubleValue (0.00005));
- Config::SetDefault ("ns3::LteSpectrumPhy::PemEnabled", BooleanValue (false));
- LogComponentDisableAll (LOG_LEVEL_ALL);
+ Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+ Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false)); LogComponentDisableAll (LOG_LEVEL_ALL);
// LogComponentEnable ("LteEnbRrc", LOG_LEVEL_ALL);
// LogComponentEnable ("LteUeRrc", LOG_LEVEL_ALL);
// LogComponentEnable ("LteEnbMac", LOG_LEVEL_ALL);
--- a/src/lte/test/lte-test-phy-error-model.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/lte-test-phy-error-model.cc Tue Jul 31 19:18:23 2012 +0200
@@ -46,6 +46,7 @@
#include <ns3/boolean.h>
#include <ns3/enum.h>
#include <ns3/unused.h>
+#include <ns3/ff-mac-scheduler.h>
#include "lte-test-phy-error-model.h"
@@ -58,20 +59,32 @@
: TestSuite ("lte-phy-error-model", SYSTEM)
{
NS_LOG_INFO ("creating LenaTestPhyErrorModelTestCase");
+
+
+ // Tests on DL Control Channels (PCFICH+PDDCH)
+ // 1 interfering eNB SINR -2.0 BER 0.007 TB size 217
+ AddTestCase (new LenaDlCtrlPhyErrorModelTestCase (2, 1078, 217, 0.007));
+ // 2 interfering eNBs SINR -4.0 BER 0.037 TB size 217
+ AddTestCase (new LenaDlCtrlPhyErrorModelTestCase (3, 1040, 217, 0.045));
+ // 3 interfering eNBs SINR -6.0 BER 0.21 TB size 133
+ AddTestCase (new LenaDlCtrlPhyErrorModelTestCase (4, 1250, 133, 0.206));
+ // 4 interfering eNBs SINR -7.0 BER 0.34 TB size 133
+ AddTestCase (new LenaDlCtrlPhyErrorModelTestCase (5, 1260, 81, 0.343));
+ // Tests on DL/UL Data channels (PDSCH, PUSCH)
// MCS 2 TB size of 256 bits BER 0.33 SINR -5.51
- AddTestCase (new LenaPhyErrorModelTestCase (4, 1800, 32, 0.33, 29));
+ AddTestCase (new LenaDataPhyErrorModelTestCase (4, 1800, 32, 0.35, 50));
// MCS 2 TB size of 528 bits BER 0.11 SINR -5.51
- AddTestCase (new LenaPhyErrorModelTestCase (2, 1800, 66, 0.11, 20));
+ AddTestCase (new LenaDataPhyErrorModelTestCase (2, 1800, 66, 0.11, 34));
// MCS 2 TB size of 1088 bits BER 0.02 SINR -5.51
- AddTestCase (new LenaPhyErrorModelTestCase (1, 1800, 136, 0.02, 9));
+ AddTestCase (new LenaDataPhyErrorModelTestCase (1, 1800, 136, 0.02, 16));
// MCS 12 TB size of 4800 bits BER 0.3 SINR 4.43
- AddTestCase (new LenaPhyErrorModelTestCase (1, 600, 600, 0.3, 29));
+ AddTestCase (new LenaDataPhyErrorModelTestCase (1, 600, 600, 0.3, 48));
// MCS 12 TB size of 1632 bits BER 0.55 SINR 4.43
- AddTestCase (new LenaPhyErrorModelTestCase (3, 600, 204, 0.55, 31));
+ AddTestCase (new LenaDataPhyErrorModelTestCase (3, 600, 204, 0.55, 52));
// MCS 16 TB size of 7272 bits (3648 x 3584) BER 0.14 SINR 8.48
// BER 0.14 = 1 - ((1-0.075)*(1-0.075))
- AddTestCase (new LenaPhyErrorModelTestCase (1, 470, 781, 0.14, 22));
+ AddTestCase (new LenaDataPhyErrorModelTestCase (1, 470, 781, 0.14, 29));
@@ -80,14 +93,14 @@
static LenaTestPhyErrorModelrSuite lenaTestPhyErrorModelrSuite;
std::string
-LenaPhyErrorModelTestCase::BuildNameString (uint16_t nUser, uint16_t dist)
+LenaDataPhyErrorModelTestCase::BuildNameString (uint16_t nUser, uint16_t dist)
{
std::ostringstream oss;
oss << nUser << " UEs, distance " << dist << " m";
return oss.str ();
}
-LenaPhyErrorModelTestCase::LenaPhyErrorModelTestCase (uint16_t nUser, uint16_t dist, uint16_t tbSize, double berRef, uint16_t bernQuantile)
+LenaDataPhyErrorModelTestCase::LenaDataPhyErrorModelTestCase (uint16_t nUser, uint16_t dist, uint16_t tbSize, double berRef, uint16_t bernQuantile)
: TestCase (BuildNameString (nUser, dist)),
m_nUser (nUser),
m_dist (dist),
@@ -97,19 +110,19 @@
{
}
-LenaPhyErrorModelTestCase::~LenaPhyErrorModelTestCase ()
+LenaDataPhyErrorModelTestCase::~LenaDataPhyErrorModelTestCase ()
{
}
void
-LenaPhyErrorModelTestCase::DoRun (void)
+LenaDataPhyErrorModelTestCase::DoRun (void)
{
double ber = 0.03;
Config::SetDefault ("ns3::LteAmc::Ber", DoubleValue (ber));
Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
- Config::SetDefault ("ns3::LteSpectrumPhy::PemEnabled", BooleanValue (true));
-
+ Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+ Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (true));
// LogComponentEnable ("LteEnbRrc", LOG_LEVEL_ALL);
// LogComponentEnable ("LteUeRrc", LOG_LEVEL_ALL);
// LogComponentEnable ("LteEnbMac", LOG_LEVEL_ALL);
@@ -151,7 +164,7 @@
// LogComponentEnable ("LteAmc", LOG_LEVEL_ALL);
//
LogComponentDisableAll (LOG_LEVEL_ALL);
-
+
LogComponentEnable ("LenaTestPhyErrorModel", LOG_LEVEL_ALL);
@@ -184,6 +197,7 @@
NetDeviceContainer enbDevs;
NetDeviceContainer ueDevs;
lena->SetSchedulerType ("ns3::RrFfMacScheduler");
+ lena->SetSchedulerAttribute ("UlCqiFilter", EnumValue (FfMacScheduler::PUSCH_UL_CQI));
enbDevs = lena->InstallEnbDevice (enbNodes);
ueDevs = lena->InstallUeDevice (ueNodes);
@@ -218,6 +232,7 @@
lena->EnableRlcTraces ();
double simulationTime = 1.000;
+
Simulator::Stop (Seconds (simulationTime));
Ptr<RadioBearerStatsCalculator> rlcStats = lena->GetRlcStats ();
@@ -229,6 +244,7 @@
/**
* Check that the assignation is done in a RR fashion
*/
+ NS_LOG_INFO ("\tTest downlink/uplink data shared channels (PDSCH and PUSCH)");
NS_LOG_INFO ("Test with " << m_nUser << " user(s) at distance " << m_dist << " expected BER " << m_berRef);
std::vector <uint64_t> dlDataRxed;
for (int i = 0; i < m_nUser; i++)
@@ -257,6 +273,184 @@
Simulator::Destroy ();
}
-} // namespace ns3
+
+
+
+std::string
+LenaDlCtrlPhyErrorModelTestCase::BuildNameString (uint16_t nEnb, uint16_t dist)
+{
+ std::ostringstream oss;
+ oss << nEnb << " eNBs, distance " << dist << " m";
+ return oss.str ();
+}
+LenaDlCtrlPhyErrorModelTestCase::LenaDlCtrlPhyErrorModelTestCase (uint16_t nEnb, uint16_t dist, uint16_t tbSize, double berRef)
+: TestCase (BuildNameString (nEnb, dist)),
+m_nEnb (nEnb),
+m_dist (dist),
+m_tbSize (tbSize),
+m_berRef (berRef)
+{
+}
+
+LenaDlCtrlPhyErrorModelTestCase::~LenaDlCtrlPhyErrorModelTestCase ()
+{
+}
+
+void
+LenaDlCtrlPhyErrorModelTestCase::DoRun (void)
+{
+
+ double ber = 0.03;
+ Config::SetDefault ("ns3::LteAmc::Ber", DoubleValue (ber));
+ Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
+ Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (true));
+ Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
+ // LogComponentEnable ("LteEnbRrc", LOG_LEVEL_ALL);
+ // LogComponentEnable ("LteUeRrc", LOG_LEVEL_ALL);
+ // LogComponentEnable ("LteEnbMac", LOG_LEVEL_ALL);
+ // LogComponentEnable ("LteUeMac", LOG_LEVEL_ALL);
+ // LogComponentEnable ("LteRlc", LOG_LEVEL_ALL);
+ //
+ // LogComponentEnable ("LtePhy", LOG_LEVEL_ALL);
+ // LogComponentEnable ("LteEnbPhy", LOG_LEVEL_ALL);
+ // LogComponentEnable ("LteUePhy", LOG_LEVEL_ALL);
+
+ // LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL);
+ // LogComponentEnable ("LteInterference", LOG_LEVEL_ALL);
+ // LogComponentEnable ("LteSinrChunkProcessor", LOG_LEVEL_ALL);
+ //
+ // LogComponentEnable ("LtePropagationLossModel", LOG_LEVEL_ALL);
+ // LogComponentEnable ("LossModel", LOG_LEVEL_ALL);
+ // LogComponentEnable ("ShadowingLossModel", LOG_LEVEL_ALL);
+ // LogComponentEnable ("PenetrationLossModel", LOG_LEVEL_ALL);
+ // LogComponentEnable ("MultipathLossModel", LOG_LEVEL_ALL);
+ // LogComponentEnable ("PathLossModel", LOG_LEVEL_ALL);
+ //
+ // LogComponentEnable ("LteNetDevice", LOG_LEVEL_ALL);
+ // LogComponentEnable ("LteUeNetDevice", LOG_LEVEL_ALL);
+ // LogComponentEnable ("LteEnbNetDevice", LOG_LEVEL_ALL);
+
+// LogComponentEnable ("RrFfMacScheduler", LOG_LEVEL_ALL);
+ // LogComponentEnable ("LenaHelper", LOG_LEVEL_ALL);
+ // LogComponentEnable ("RlcStatsCalculator", LOG_LEVEL_ALL);
+
+
+ // LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL);
+ // LogComponentEnable ("LteEnbMac", LOG_LEVEL_ALL);
+ // LogComponentEnable ("LteEnbPhy", LOG_LEVEL_ALL);
+ // LogComponentEnable ("LteUePhy", LOG_LEVEL_ALL);
+ // LogComponentEnable ("RrFfMacScheduler", LOG_LEVEL_ALL);
+ // LogComponentEnable ("LenaHelper", LOG_LEVEL_ALL);
+ // LogComponentEnable ("BuildingsPropagationLossModel", LOG_LEVEL_ALL);
+// LogComponentEnable ("LteMiErrorModel", LOG_LEVEL_ALL);
+ // LogComponentEnable ("LteAmc", LOG_LEVEL_ALL);
+ //
+ LogComponentDisableAll (LOG_LEVEL_ALL);
+
+ LogComponentEnable ("LenaTestPhyErrorModel", LOG_LEVEL_ALL);
+
+
+ /**
+ * Initialize Simulation Scenario: 1 eNB and m_nUser UEs
+ */
+
+ Ptr<LteHelper> lena = CreateObject<LteHelper> ();
+
+ // Create Nodes: eNodeB and UE
+ NodeContainer enbNodes;
+ NodeContainer ueNodes;
+ enbNodes.Create (m_nEnb);
+ ueNodes.Create (1);
+
+ // Install Mobility Model
+ MobilityHelper mobility;
+ mobility.SetMobilityModel ("ns3::BuildingsMobilityModel");
+ mobility.Install (enbNodes);
+ mobility.SetMobilityModel ("ns3::BuildingsMobilityModel");
+ mobility.Install (ueNodes);
+
+ // remove random shadowing component
+ lena->SetAttribute ("PathlossModel", StringValue ("ns3::HybridBuildingsPropagationLossModel"));
+ lena->SetPathlossModelAttribute ("ShadowSigmaOutdoor", DoubleValue (0.0));
+ lena->SetPathlossModelAttribute ("ShadowSigmaIndoor", DoubleValue (0.0));
+ lena->SetPathlossModelAttribute ("ShadowSigmaExtWalls", DoubleValue (0.0));
+
+ // Create Devices and install them in the Nodes (eNB and UE)
+ NetDeviceContainer enbDevs;
+ NetDeviceContainer ueDevs;
+ lena->SetSchedulerType ("ns3::RrFfMacScheduler");
+ lena->SetSchedulerAttribute ("UlCqiFilter", EnumValue (FfMacScheduler::PUSCH_UL_CQI));
+
+ enbDevs = lena->InstallEnbDevice (enbNodes);
+ ueDevs = lena->InstallUeDevice (ueNodes);
+
+ // Attach a UE to one eNB (the others are interfering ones)
+ lena->Attach (ueDevs, enbDevs.Get (0));
+
+ // Activate an EPS bearer
+ enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
+ EpsBearer bearer (q);
+ lena->ActivateDataRadioBearer (ueDevs, bearer);
+
+ // Set UEs' position and power
+ for (int i = 0; i < m_nEnb; i++)
+ {
+ // place the HeNB over the default rooftop level (20 mt.)
+ Ptr<BuildingsMobilityModel> mm = enbNodes.Get (i)->GetObject<BuildingsMobilityModel> ();
+ mm->SetPosition (Vector (0.0, 0.0, 30.0));
+ Ptr<LteEnbNetDevice> lteEnbDev = enbDevs.Get (i)->GetObject<LteEnbNetDevice> ();
+ Ptr<LteEnbPhy> enbPhy = lteEnbDev->GetPhy ();
+ enbPhy->SetAttribute ("TxPower", DoubleValue (43.0));
+ enbPhy->SetAttribute ("NoiseFigure", DoubleValue (5.0));
+ }
+
+ // Set UEs' position and power
+ Ptr<BuildingsMobilityModel> mm = ueNodes.Get (0)->GetObject<BuildingsMobilityModel> ();
+ mm->SetPosition (Vector (m_dist, 0.0, 1.0));
+ Ptr<LteUeNetDevice> lteUeDev = ueDevs.Get (0)->GetObject<LteUeNetDevice> ();
+ Ptr<LteUePhy> uePhy = lteUeDev->GetPhy ();
+ uePhy->SetAttribute ("TxPower", DoubleValue (23.0));
+ uePhy->SetAttribute ("NoiseFigure", DoubleValue (9.0));
+
+
+ lena->EnableRlcTraces ();
+ double simulationTime = 1.000;
+
+ Simulator::Stop (Seconds (simulationTime));
+
+ Ptr<RadioBearerStatsCalculator> rlcStats = lena->GetRlcStats ();
+ rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (simulationTime)));
+
+
+ Simulator::Run ();
+
+ /**
+ * Check that the assignation is done in a RR fashion
+ */
+ NS_LOG_INFO ("\tTest downlink control channels (PCFICH+PDCCH)");
+ NS_LOG_INFO ("Test with " << m_nEnb << " eNB(s) at distance " << m_dist << " expected BER " << m_berRef);
+ std::vector <uint64_t> dlDataRxed;
+ int nUser = 1;
+ for (int i = 0; i < nUser; i++)
+ {
+ // get the imsi
+ uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
+ // get the lcId
+ uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+ dlDataRxed.push_back (rlcStats->GetDlRxData (imsi, lcId));
+ double txed = rlcStats->GetDlTxData (imsi, lcId);
+ double ber = 1.0 - ((double)dlDataRxed.at (i)/txed);
+ NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " bytes rxed " << (double)dlDataRxed.at (i) << " txed " << txed
+ << " BER " << ber << " Err " << fabs (m_berRef - ber));
+ NS_UNUSED (ber);
+ NS_TEST_ASSERT_MSG_EQ_TOL (ber, m_berRef, 0.1, " Unexpected BER distribution!");
+ }
+
+
+ Simulator::Destroy ();
+}
+
+
+} // namespace
--- a/src/lte/test/lte-test-phy-error-model.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/lte-test-phy-error-model.h Tue Jul 31 19:18:23 2012 +0200
@@ -35,11 +35,11 @@
* implemented obtained by using different SINR values and different numbers of
* UEs. The test consists on ...
*/
-class LenaPhyErrorModelTestCase : public TestCase
+class LenaDataPhyErrorModelTestCase : public TestCase
{
public:
- LenaPhyErrorModelTestCase (uint16_t nUser, uint16_t dist, uint16_t tbSize, double refBer, uint16_t bernQuantile);
- virtual ~LenaPhyErrorModelTestCase ();
+ LenaDataPhyErrorModelTestCase (uint16_t nUser, uint16_t dist, uint16_t tbSize, double refBer, uint16_t bernQuantile);
+ virtual ~LenaDataPhyErrorModelTestCase ();
private:
virtual void DoRun (void);
@@ -54,6 +54,24 @@
+class LenaDlCtrlPhyErrorModelTestCase : public TestCase
+{
+ public:
+ LenaDlCtrlPhyErrorModelTestCase (uint16_t nEnbr, uint16_t dist, uint16_t tbSize, double refBer);
+ virtual ~LenaDlCtrlPhyErrorModelTestCase ();
+
+ private:
+ virtual void DoRun (void);
+ static std::string BuildNameString (uint16_t nUser, uint16_t dist);
+ uint16_t m_nEnb;
+ uint16_t m_dist;
+ uint16_t m_tbSize;
+ double m_berRef;
+
+};
+
+
+
class LenaTestPhyErrorModelrSuite : public TestSuite
{
public:
--- a/src/lte/test/lte-test-rr-ff-mac-scheduler.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/lte-test-rr-ff-mac-scheduler.cc Tue Jul 31 19:18:23 2012 +0200
@@ -191,8 +191,8 @@
void
LenaRrFfMacSchedulerTestCase::DoRun (void)
{
- Config::SetDefault ("ns3::LteSpectrumPhy::PemEnabled", BooleanValue (false));
- Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
+ Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+ Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false)); Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
Config::SetDefault ("ns3::LteAmc::Ber", DoubleValue (0.00005));
LogComponentDisableAll (LOG_LEVEL_ALL);
// LogComponentEnable ("LteEnbRrc", LOG_LEVEL_ALL);
--- a/src/lte/test/lte-test-sinr-chunk-processor.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/lte-test-sinr-chunk-processor.cc Tue Jul 31 19:18:23 2012 +0200
@@ -84,6 +84,7 @@
{
NS_LOG_FUNCTION (this);
+ NS_ASSERT (m_sinr);
return m_sinr;
}
--- a/src/lte/test/lte-test-ue-phy.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/lte-test-ue-phy.cc Tue Jul 31 19:18:23 2012 +0200
@@ -78,7 +78,7 @@
}
void
-LteTestUePhy::GenerateCqiReport (const SpectrumValue& sinr)
+LteTestUePhy::GenerateCtrlCqiReport (const SpectrumValue& sinr)
{
NS_LOG_FUNCTION (this);
@@ -87,7 +87,16 @@
}
void
-LteTestUePhy::ReceiveIdealControlMessage (Ptr<IdealControlMessage> msg)
+LteTestUePhy::GenerateDataCqiReport (const SpectrumValue& sinr)
+{
+ NS_LOG_FUNCTION (this);
+
+ // Store calculated SINR, it will be retrieved at the end of the test
+ m_sinr = sinr;
+}
+
+void
+LteTestUePhy::ReceiveLteControlMessage (Ptr<LteControlMessage> msg)
{
NS_LOG_FUNCTION (this << msg);
}
--- a/src/lte/test/lte-test-ue-phy.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/lte-test-ue-phy.h Tue Jul 31 19:18:23 2012 +0200
@@ -23,7 +23,7 @@
#include "ns3/lte-phy.h"
-#include "ns3/ideal-control-messages.h"
+#include "ns3/lte-control-messages.h"
namespace ns3 {
@@ -58,9 +58,11 @@
*/
virtual Ptr<SpectrumValue> CreateTxPowerSpectralDensity ();
- virtual void GenerateCqiReport (const SpectrumValue& sinr);
+ virtual void GenerateCtrlCqiReport (const SpectrumValue& sinr);
+
+ virtual void GenerateDataCqiReport (const SpectrumValue& sinr);
- virtual void ReceiveIdealControlMessage (Ptr<IdealControlMessage> msg);
+ virtual void ReceiveLteControlMessage (Ptr<LteControlMessage> msg);
SpectrumValue GetSinr ();
--- a/src/lte/test/lte-test-uplink-sinr.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/lte-test-uplink-sinr.cc Tue Jul 31 19:18:23 2012 +0200
@@ -16,6 +16,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Manuel Requena <manuel.requena@cttc.es>
+ * Modified by Marco Miozzo <mmiozzo@ctt.es>
+ * Extend to Data and SRS frames
*/
#include "ns3/simulator.h"
@@ -25,12 +27,14 @@
#include "ns3/spectrum-test.h"
#include "ns3/lte-phy-tag.h"
-#include "ns3/lte-sinr-chunk-processor.h"
+#include "ns3/lte-test-ue-phy.h"
+#include "ns3/lte-test-sinr-chunk-processor.h"
#include "ns3/lte-spectrum-signal-parameters.h"
-#include "lte-test-ue-phy.h"
#include "lte-test-uplink-sinr.h"
+#include <ns3/lte-helper.h>
+
NS_LOG_COMPONENT_DEFINE ("LteUplinkSinrTest");
namespace ns3 {
@@ -81,7 +85,9 @@
(*theoreticalSinr1)[0] = 3.72589167251055;
(*theoreticalSinr1)[1] = 3.72255684126076;
- AddTestCase (new LteUplinkSinrTestCase (rxPsd1, rxPsd2, theoreticalSinr1, "sdBm = [-46 -inf] and [-inf -48]"));
+ AddTestCase (new LteUplinkDataSinrTestCase (rxPsd1, rxPsd2, theoreticalSinr1, "sdBm = [-46 -inf] and [-inf -48]"));
+
+ AddTestCase (new LteUplinkSrsSinrTestCase (rxPsd1, rxPsd2, theoreticalSinr1, "sdBm = [-46 -inf] and [-inf -48]"));
/**
* TX signals #2: Power Spectral Density of the signals of interest = [-63 -inf] and [-inf -61] dBm and BW = [20 22] MHz
@@ -98,7 +104,9 @@
(*theoreticalSinr2)[0] = 0.0743413124381667;
(*theoreticalSinr2)[1] = 0.1865697965291756;
- AddTestCase (new LteUplinkSinrTestCase (rxPsd3, rxPsd4, theoreticalSinr2, "sdBm = [-63 -inf] and [-inf -61]"));
+ AddTestCase (new LteUplinkDataSinrTestCase (rxPsd3, rxPsd4, theoreticalSinr2, "sdBm = [-63 -inf] and [-inf -61]"));
+
+ AddTestCase (new LteUplinkSrsSinrTestCase (rxPsd3, rxPsd4, theoreticalSinr2, "sdBm = [-63 -inf] and [-inf -61]"));
}
@@ -106,25 +114,25 @@
/**
- * TestCase
+ * TestCase Data
*/
-LteUplinkSinrTestCase::LteUplinkSinrTestCase (Ptr<SpectrumValue> sv1, Ptr<SpectrumValue> sv2, Ptr<SpectrumValue> sinr, std::string name)
- : TestCase ("SINR calculation in uplink: " + name),
+LteUplinkDataSinrTestCase::LteUplinkDataSinrTestCase (Ptr<SpectrumValue> sv1, Ptr<SpectrumValue> sv2, Ptr<SpectrumValue> sinr, std::string name)
+ : TestCase ("SINR calculation in uplink data frame: " + name),
m_sv1 (sv1),
m_sv2 (sv2),
m_sm (sv1->GetSpectrumModel ()),
m_sinr (sinr)
{
- NS_LOG_INFO ("Creating LteUplinkSinrTestCase");
+ NS_LOG_INFO ("Creating LteUplinkDataSinrTestCase");
}
-LteUplinkSinrTestCase::~LteUplinkSinrTestCase ()
+LteUplinkDataSinrTestCase::~LteUplinkDataSinrTestCase ()
{
}
void
-LteUplinkSinrTestCase::DoRun (void)
+LteUplinkDataSinrTestCase::DoRun (void)
{
/**
* Instantiate a single receiving LteSpectrumPhy
@@ -132,18 +140,20 @@
Ptr<LteSpectrumPhy> dlPhy = CreateObject<LteSpectrumPhy> ();
Ptr<LteSpectrumPhy> ulPhy = CreateObject<LteSpectrumPhy> ();
Ptr<LteTestUePhy> uePhy = CreateObject<LteTestUePhy> (dlPhy, ulPhy);
-
- ulPhy->SetCellId (100);
+ uint16_t cellId = 100;
+ dlPhy->SetCellId (cellId);
+ ulPhy->SetCellId (cellId);
- Ptr<LteCqiSinrChunkProcessor> chunkProcessor = Create<LteCqiSinrChunkProcessor> (uePhy->GetObject<LtePhy> ());
- ulPhy->AddSinrChunkProcessor (chunkProcessor);
+ Ptr<LteTestSinrChunkProcessor> chunkProcessor = Create<LteTestSinrChunkProcessor> (uePhy->GetObject<LtePhy> ());
+ ulPhy->AddDataSinrChunkProcessor (chunkProcessor);
/**
- * Generate several calls to LteSpectrumPhy::StartRx corresponding to several signals.
- * One will be the signal of interest, i.e., the PhyTag of the first Packet in the Packet burst
- * will have the same CellId of the receiving PHY;
- * the others will have a different CellId and hence will be the interfering signals
- */
+ * Generate several calls to LteSpectrumPhy::StartRx corresponding to
+ * several signals. One will be the signal of interest, i.e., the
+ * LteSpectrumSignalParametersDataFrame of the Packet burst
+ * will have the same CellId of the receiving PHY; the others will have
+ * a different CellId and hence will be the interfering signals
+ */
// Number of packet bursts (2 data + 4 interferences)
int numOfDataPbs = 2;
@@ -159,8 +169,9 @@
// Packets
Ptr<Packet> pkt[numOfPbs][numOfPkts];
- // Phy tags
- LtePhyTag pktTag[numOfPbs];
+ // Bursts cellId
+ uint16_t pbCellId[numOfPbs];
+
/**
@@ -171,20 +182,12 @@
{
// Create packet burst
packetBursts[pb] = CreateObject<PacketBurst> ();
-
+ pbCellId[pb] = cellId;
// Create packets and add them to the burst
for ( int i = 0 ; i < numOfPkts ; i++ )
{
pkt[pb][i] = Create<Packet> (1000);
- if ( i == 0 )
- {
- // Create phy tag (same for all data packet burst)
- // and add to the first packet
- pktTag[pb] = LtePhyTag (100);
- pkt[pb][i]->AddPacketTag ( pktTag[pb] );
- }
-
packetBursts[pb]->AddPacket ( pkt[pb][i] );
}
}
@@ -192,20 +195,13 @@
{
// Create packet burst
packetBursts[pb] = CreateObject<PacketBurst> ();
+ pbCellId[pb] = cellId * (pb + 1);
// Create packets and add them to the burst
for ( int i = 0 ; i < numOfPkts ; i++ )
{
pkt[pb][i] = Create<Packet> (1000);
- if ( i == 0 )
- {
- // Create phy tag (different for each packet burst)
- // and add to the first packet
- pktTag[pb] = LtePhyTag (100 * (pb + 1));
- pkt[pb][i]->AddPacketTag ( pktTag[pb] );
- }
-
packetBursts[pb]->AddPacket ( pkt[pb][i] );
}
}
@@ -247,47 +243,53 @@
*/
// 2 UEs send data to the eNB through 2 subcarriers
- Ptr<LteSpectrumSignalParameters> sp1 = Create<LteSpectrumSignalParameters> ();
+ Ptr<LteSpectrumSignalParametersDataFrame> sp1 = Create<LteSpectrumSignalParametersDataFrame> ();
sp1->psd = m_sv1;
sp1->txPhy = 0;
sp1->duration = ds;
sp1->packetBurst = packetBursts[0];
+ sp1->cellId = pbCellId[0];
Simulator::Schedule (ts, &LteSpectrumPhy::StartRx, ulPhy, sp1);
- Ptr<LteSpectrumSignalParameters> sp2 = Create<LteSpectrumSignalParameters> ();
+ Ptr<LteSpectrumSignalParametersDataFrame> sp2 = Create<LteSpectrumSignalParametersDataFrame> ();
sp2->psd = m_sv2;
sp2->txPhy = 0;
sp2->duration = ds;
sp2->packetBurst = packetBursts[1];
+ sp2->cellId = pbCellId[1];
Simulator::Schedule (ts, &LteSpectrumPhy::StartRx, ulPhy, sp2);
- Ptr<LteSpectrumSignalParameters> ip1 = Create<LteSpectrumSignalParameters> ();
+ Ptr<LteSpectrumSignalParametersDataFrame> ip1 = Create<LteSpectrumSignalParametersDataFrame> ();
ip1->psd = i1;
ip1->txPhy = 0;
ip1->duration = di1;
ip1->packetBurst = packetBursts[2];
+ ip1->cellId = pbCellId[2];
Simulator::Schedule (ti1, &LteSpectrumPhy::StartRx, ulPhy, ip1);
- Ptr<LteSpectrumSignalParameters> ip2 = Create<LteSpectrumSignalParameters> ();
+ Ptr<LteSpectrumSignalParametersDataFrame> ip2 = Create<LteSpectrumSignalParametersDataFrame> ();
ip2->psd = i2;
ip2->txPhy = 0;
ip2->duration = di2;
ip2->packetBurst = packetBursts[3];
+ ip2->cellId = pbCellId[3];
Simulator::Schedule (ti2, &LteSpectrumPhy::StartRx, ulPhy, ip2);
- Ptr<LteSpectrumSignalParameters> ip3 = Create<LteSpectrumSignalParameters> ();
+ Ptr<LteSpectrumSignalParametersDataFrame> ip3 = Create<LteSpectrumSignalParametersDataFrame> ();
ip3->psd = i3;
ip3->txPhy = 0;
ip3->duration = di3;
ip3->packetBurst = packetBursts[4];
+ ip3->cellId = pbCellId[4];
Simulator::Schedule (ti3, &LteSpectrumPhy::StartRx, ulPhy, ip3);
- Ptr<LteSpectrumSignalParameters> ip4 = Create<LteSpectrumSignalParameters> ();
+ Ptr<LteSpectrumSignalParametersDataFrame> ip4 = Create<LteSpectrumSignalParametersDataFrame> ();
ip4->psd = i4;
ip4->txPhy = 0;
ip4->duration = di4;
ip4->packetBurst = packetBursts[5];
+ ip4->cellId = pbCellId[5];
Simulator::Schedule (ti4, &LteSpectrumPhy::StartRx, ulPhy, ip4);
Simulator::Stop (Seconds (5.0));
@@ -297,16 +299,185 @@
* Check that the values passed to LteSinrChunkProcessor::EvaluateSinrChunk () correspond
* to known values which have been calculated offline (with octave) for the generated signals
*/
- SpectrumValue calculatedSinr = uePhy->GetSinr ();
+ Ptr<SpectrumValue> calculatedSinr = chunkProcessor->GetSinr ();
- NS_LOG_INFO ("Theoretical SINR: " << *m_sinr);
- NS_LOG_INFO ("Calculated SINR: " << calculatedSinr);
+ NS_LOG_INFO ("Data Frame - Theoretical SINR: " << *m_sinr);
+ NS_LOG_INFO ("Data Frame - Calculated SINR: " << *calculatedSinr);
- NS_TEST_ASSERT_MSG_SPECTRUM_VALUE_EQ_TOL (calculatedSinr, *m_sinr, 0.0000001, "Wrong SINR !");
+ NS_TEST_ASSERT_MSG_SPECTRUM_VALUE_EQ_TOL (*calculatedSinr, *m_sinr, 0.0000001, "Data Frame - Wrong SINR !");
ulPhy->Dispose ();
Simulator::Destroy ();
}
-} // namespace ns3
+
+/**
+* TestCase Srs
+*/
+
+LteUplinkSrsSinrTestCase::LteUplinkSrsSinrTestCase (Ptr<SpectrumValue> sv1, Ptr<SpectrumValue> sv2, Ptr<SpectrumValue> sinr, std::string name)
+: TestCase ("SINR calculation in uplink srs frame: " + name),
+m_sv1 (sv1),
+m_sv2 (sv2),
+m_sm (sv1->GetSpectrumModel ()),
+m_sinr (sinr)
+{
+ NS_LOG_INFO ("Creating LteUplinkSrsSinrTestCase");
+}
+
+LteUplinkSrsSinrTestCase::~LteUplinkSrsSinrTestCase ()
+{
+}
+
+void
+LteUplinkSrsSinrTestCase::DoRun (void)
+{
+ /**
+ * Instantiate a single receiving LteSpectrumPhy
+ */
+
+ Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+ lteHelper->EnableLogComponents ();
+ Ptr<LteSpectrumPhy> dlPhy = CreateObject<LteSpectrumPhy> ();
+ Ptr<LteSpectrumPhy> ulPhy = CreateObject<LteSpectrumPhy> ();
+ Ptr<LteTestUePhy> uePhy = CreateObject<LteTestUePhy> (dlPhy, ulPhy);
+ uint16_t cellId = 100;
+ dlPhy->SetCellId (cellId);
+ ulPhy->SetCellId (cellId);
+
+ Ptr<LteTestSinrChunkProcessor> chunkProcessor = Create<LteTestSinrChunkProcessor> (uePhy->GetObject<LtePhy> ());
+ ulPhy->AddCtrlSinrChunkProcessor (chunkProcessor);
+
+ /**
+ * Generate several calls to LteSpectrumPhy::StartRx corresponding to
+ * several signals.
+ * One will be the signal of interest, i.e., the
+ * LteSpectrumSignalParametersUlSrsFrame of the first signal will have the
+ * same CellId of the receiving PHY; the others will have a different
+ * CellId and hence will be the interfering signals
+ */
+
+ // Number of packet bursts (2 data + 4 interferences)
+ int numOfDataSignals = 2;
+ int numOfIntfSignals = 4;
+ int numOfSignals = numOfDataSignals + numOfIntfSignals;
+
+ uint16_t pbCellId[numOfSignals];
+
+
+
+ /**
+ * Build packet burst (Data and interference)
+ */
+ int pb = 0;
+ for ( int dataPb = 0 ; dataPb < numOfDataSignals ; dataPb++, pb++ )
+ {
+ pbCellId[pb] = cellId;
+
+ }
+ for ( int intfPb = 0 ; intfPb < numOfIntfSignals ; intfPb++, pb++ )
+ {
+
+ pbCellId[pb] = cellId * (pb + 1);
+ }
+
+
+ Ptr<SpectrumValue> noisePsd = Create<SpectrumValue> (m_sm);
+ Ptr<SpectrumValue> i1 = Create<SpectrumValue> (m_sm);
+ Ptr<SpectrumValue> i2 = Create<SpectrumValue> (m_sm);
+ Ptr<SpectrumValue> i3 = Create<SpectrumValue> (m_sm);
+ Ptr<SpectrumValue> i4 = Create<SpectrumValue> (m_sm);
+
+ (*noisePsd)[0] = 5.000000000000e-19;
+ (*noisePsd)[1] = 4.545454545455e-19;
+
+ (*i1)[0] = 5.000000000000e-18;
+ (*i2)[0] = 5.000000000000e-16;
+ (*i3)[0] = 1.581138830084e-16;
+ (*i4)[0] = 7.924465962306e-17;
+ (*i1)[1] = 1.437398936440e-18;
+ (*i2)[1] = 5.722388235428e-16;
+ (*i3)[1] = 7.204059965732e-17;
+ (*i4)[1] = 5.722388235428e-17;
+
+ Time ts = Seconds (1);
+ Time ds = Seconds (1);
+ Time ti1 = Seconds (0);
+ Time di1 = Seconds (3);
+ Time ti2 = Seconds (0.7);
+ Time di2 = Seconds (1);
+ Time ti3 = Seconds (1.2);
+ Time di3 = Seconds (1);
+ Time ti4 = Seconds (1.5);
+ Time di4 = Seconds (0.1);
+
+ ulPhy->SetNoisePowerSpectralDensity (noisePsd);
+
+ /**
+ * Schedule the reception of the data signals plus the interference signals
+ */
+
+ // 2 UEs send data to the eNB through 2 subcarriers
+ Ptr<LteSpectrumSignalParametersUlSrsFrame> sp1 = Create<LteSpectrumSignalParametersUlSrsFrame> ();
+ sp1->psd = m_sv1;
+ sp1->txPhy = 0;
+ sp1->duration = ds;
+ sp1->cellId = pbCellId[0];
+ Simulator::Schedule (ts, &LteSpectrumPhy::StartRx, ulPhy, sp1);
+
+ Ptr<LteSpectrumSignalParametersUlSrsFrame> sp2 = Create<LteSpectrumSignalParametersUlSrsFrame> ();
+ sp2->psd = m_sv2;
+ sp2->txPhy = 0;
+ sp2->duration = ds;
+ sp2->cellId = pbCellId[1];
+ Simulator::Schedule (ts, &LteSpectrumPhy::StartRx, ulPhy, sp2);
+
+
+ Ptr<LteSpectrumSignalParametersUlSrsFrame> ip1 = Create<LteSpectrumSignalParametersUlSrsFrame> ();
+ ip1->psd = i1;
+ ip1->txPhy = 0;
+ ip1->duration = di1;
+ ip1->cellId = pbCellId[2];
+ Simulator::Schedule (ti1, &LteSpectrumPhy::StartRx, ulPhy, ip1);
+
+ Ptr<LteSpectrumSignalParametersUlSrsFrame> ip2 = Create<LteSpectrumSignalParametersUlSrsFrame> ();
+ ip2->psd = i2;
+ ip2->txPhy = 0;
+ ip2->duration = di2;
+ ip2->cellId = pbCellId[3];
+ Simulator::Schedule (ti2, &LteSpectrumPhy::StartRx, ulPhy, ip2);
+
+ Ptr<LteSpectrumSignalParametersUlSrsFrame> ip3 = Create<LteSpectrumSignalParametersUlSrsFrame> ();
+ ip3->psd = i3;
+ ip3->txPhy = 0;
+ ip3->duration = di3;
+ ip3->cellId = pbCellId[4];
+ Simulator::Schedule (ti3, &LteSpectrumPhy::StartRx, ulPhy, ip3);
+
+ Ptr<LteSpectrumSignalParametersUlSrsFrame> ip4 = Create<LteSpectrumSignalParametersUlSrsFrame> ();
+ ip4->psd = i4;
+ ip4->txPhy = 0;
+ ip4->duration = di4;
+ ip4->cellId = pbCellId[5];
+ Simulator::Schedule (ti4, &LteSpectrumPhy::StartRx, ulPhy, ip4);
+
+ Simulator::Stop (Seconds (5.0));
+ Simulator::Run ();
+
+ /**
+ * Check that the values passed to LteSinrChunkProcessor::EvaluateSinrChunk () correspond
+ * to known values which have been calculated offline (with octave) for the generated signals
+ */
+ Ptr<SpectrumValue> calculatedSinr = chunkProcessor->GetSinr ();
+
+ NS_LOG_INFO ("SRS Frame - Theoretical SINR: " << *m_sinr);
+ NS_LOG_INFO ("SRS Frame - Calculated SINR: " << *calculatedSinr);
+
+ NS_TEST_ASSERT_MSG_SPECTRUM_VALUE_EQ_TOL (*calculatedSinr, *m_sinr, 0.0000001, "Data Frame - Wrong SINR !");
+ ulPhy->Dispose ();
+ Simulator::Destroy ();
+
+}
+
+} //namespace
--- a/src/lte/test/lte-test-uplink-sinr.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/lte-test-uplink-sinr.h Tue Jul 31 19:18:23 2012 +0200
@@ -16,6 +16,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Manuel Requena <manuel.requena@cttc.es>
+ * Modified by Marco Miozzo <mmiozzo@ctt.es>
+ * Extend to Data and SRS frames
*/
#ifndef LTE_TEST_UPLINK_SINR_H
@@ -39,11 +41,11 @@
};
-class LteUplinkSinrTestCase : public TestCase
+class LteUplinkDataSinrTestCase : public TestCase
{
public:
- LteUplinkSinrTestCase (Ptr<SpectrumValue> sv1, Ptr<SpectrumValue> sv2, Ptr<SpectrumValue> sinr, std::string name);
- virtual ~LteUplinkSinrTestCase ();
+ LteUplinkDataSinrTestCase (Ptr<SpectrumValue> sv1, Ptr<SpectrumValue> sv2, Ptr<SpectrumValue> sinr, std::string name);
+ virtual ~LteUplinkDataSinrTestCase ();
private:
virtual void DoRun (void);
@@ -55,6 +57,22 @@
};
+class LteUplinkSrsSinrTestCase : public TestCase
+{
+ public:
+ LteUplinkSrsSinrTestCase (Ptr<SpectrumValue> sv1, Ptr<SpectrumValue> sv2, Ptr<SpectrumValue> sinr, std::string name);
+ virtual ~LteUplinkSrsSinrTestCase ();
+
+ private:
+ virtual void DoRun (void);
+
+ Ptr<SpectrumValue> m_sv1;
+ Ptr<SpectrumValue> m_sv2;
+ Ptr<const SpectrumModel> m_sm;
+ Ptr<SpectrumValue> m_sinr;
+};
+
+
#endif /* LTE_TEST_UPLINK_SINR_H */
} // namespace ns3
--- a/src/lte/test/reference/bernuolliDistribution.m Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/reference/bernuolliDistribution.m Tue Jul 31 19:18:23 2012 +0200
@@ -1,8 +1,8 @@
-% Generation of the quantiles of the Bernoulli distribution at 95%
+% Generation of the quantiles of the Bernoulli distribution at 99.9%
% related to phy error model test
n = 1000;
-p_vect = [0.33 0.11 0.02 0.3 0.55 0.14];
+p_vect = [0.35 0.11 0.02 0.3 0.55 0.14];
for i=1:length(p_vect)
p = p_vect(i)
cdf = 0.0;
@@ -12,10 +12,10 @@
for k=1:n
pk = bincoeff(n,k)* p^k * (1-p)^(n-k);
cdf = cdf + pk;
- if cdf > 0.025 & kmin == 0.0
+ if cdf > 0.0005 & kmin == 0.0
kmin = lambda - k
end
- if cdf > 0.975 & kmax == 0.0
+ if cdf > 0.9995 & kmax == 0.0
kmax = k - lambda
end
end
--- a/src/lte/test/test-lte-antenna.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/test-lte-antenna.cc Tue Jul 31 19:18:23 2012 +0200
@@ -23,6 +23,8 @@
#include "ns3/log.h"
#include "ns3/string.h"
#include "ns3/double.h"
+#include "ns3/enum.h"
+#include "ns3/boolean.h"
#include "ns3/test.h"
#include "ns3/mobility-helper.h"
#include "ns3/lte-helper.h"
@@ -31,6 +33,7 @@
#include "ns3/lte-ue-net-device.h"
#include "ns3/lte-enb-phy.h"
#include "ns3/lte-enb-net-device.h"
+#include "ns3/ff-mac-scheduler.h"
#include "lte-test-sinr-chunk-processor.h"
@@ -90,7 +93,8 @@
void
LteEnbAntennaTestCase::DoRun (void)
{
-
+ Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+ Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
// use 0dB Pathloss, since we are testing only the antenna gain
@@ -117,6 +121,7 @@
NetDeviceContainer enbDevs;
NetDeviceContainer ueDevs;
lteHelper->SetSchedulerType ("ns3::RrFfMacScheduler");
+ lteHelper->SetSchedulerAttribute ("UlCqiFilter", EnumValue (FfMacScheduler::PUSCH_UL_CQI));
lteHelper->SetEnbAntennaModelType ("ns3::CosineAntennaModel");
lteHelper->SetEnbAntennaModelAttribute ("Orientation", DoubleValue (m_orientationDegrees));
lteHelper->SetEnbAntennaModelAttribute ("Beamwidth", DoubleValue (m_beamwidthDegrees));
@@ -137,11 +142,11 @@
// It will be used to test that the SNR is as intended
Ptr<LtePhy> uePhy = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
Ptr<LteTestSinrChunkProcessor> testDlSinr = Create<LteTestSinrChunkProcessor> (uePhy);
- uePhy->GetDownlinkSpectrumPhy ()->AddSinrChunkProcessor (testDlSinr);
+ uePhy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testDlSinr);
Ptr<LtePhy> enbphy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
Ptr<LteTestSinrChunkProcessor> testUlSinr = Create<LteTestSinrChunkProcessor> (enbphy);
- enbphy->GetUplinkSpectrumPhy ()->AddSinrChunkProcessor (testUlSinr);
+ enbphy->GetUplinkSpectrumPhy ()->AddDataSinrChunkProcessor (testUlSinr);
Simulator::Stop (Seconds (0.020));
--- a/src/lte/test/test-lte-epc-e2e-data.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/test/test-lte-epc-e2e-data.cc Tue Jul 31 19:18:23 2012 +0200
@@ -109,8 +109,8 @@
void
LteEpcE2eDataTestCase::DoRun ()
{
- Config::SetDefault ("ns3::LteSpectrumPhy::PemEnabled", BooleanValue (false));
- Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
+ Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+ Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false)); Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
Ptr<EpcHelper> epcHelper = CreateObject<EpcHelper> ();
lteHelper->SetEpcHelper (epcHelper);
--- a/src/lte/wscript Sun Jul 29 14:29:41 2012 +0200
+++ b/src/lte/wscript Tue Jul 31 19:18:23 2012 +0200
@@ -32,7 +32,7 @@
'model/lte-net-device.cc',
'model/lte-enb-net-device.cc',
'model/lte-ue-net-device.cc',
- 'model/ideal-control-messages.cc',
+ 'model/lte-control-messages.cc',
'helper/lte-helper.cc',
'helper/lte-stats-calculator.cc',
'helper/epc-helper.cc',
@@ -41,6 +41,7 @@
'helper/radio-environment-map-helper.cc',
'helper/lte-hex-grid-enb-topology-helper.cc',
'model/rem-spectrum-phy.cc',
+ 'model/ff-mac-common.cc',
'model/ff-mac-csched-sap.cc',
'model/ff-mac-sched-sap.cc',
'model/lte-mac-sap.cc',
@@ -69,6 +70,7 @@
'model/epc-tft.cc',
'model/epc-tft-classifier.cc',
'model/lte-mi-error-model.cc',
+ 'model/lte-vendor-specific-parameters.cc',
'model/epc-enb-s1-sap.cc',
'model/lte-as-sap.cc',
'model/epc-ue-nas.cc',
@@ -135,7 +137,7 @@
'model/lte-net-device.h',
'model/lte-enb-net-device.h',
'model/lte-ue-net-device.h',
- 'model/ideal-control-messages.h',
+ 'model/lte-control-messages.h',
'helper/lte-helper.h',
'helper/lte-stats-calculator.h',
'helper/epc-helper.h',
@@ -167,12 +169,15 @@
'model/epc-gtpu-header.h',
'model/epc-enb-application.h',
'model/epc-sgw-pgw-application.h',
+ 'model/lte-vendor-specific-parameters.h',
'model/epc-x2-sap.h',
'model/epc-x2-header.h',
'model/epc-x2.h',
'model/epc-tft.h',
'model/epc-tft-classifier.h',
'model/lte-mi-error-model.h',
+ 'test/lte-test-ue-phy.h',
+ 'test/lte-test-sinr-chunk-processor.h',
'model/epc-enb-s1-sap.h',
'model/lte-as-sap.h',
'model/epc-ue-nas.h',
--- a/src/mobility/test/ns2-mobility-helper-test-suite.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/mobility/test/ns2-mobility-helper-test-suite.cc Tue Jul 31 19:18:23 2012 +0200
@@ -93,6 +93,7 @@
* Create new test case. To make it useful SetTrace () and AddReferencePoint () must be called
*
* \param name Short description
+ * \param timeLimit Test time limit
* \param nodes Number of nodes used in the test trace, 1 by default
*/
Ns2MobilityHelperTest (std::string const & name, Time timeLimit, uint32_t nodes = 1)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/netanim/examples/uan-animation.cc Tue Jul 31 19:18:23 2012 +0200
@@ -0,0 +1,301 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Andrea Sacco
+ *
+ * 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: Andrea Sacco <andrea.sacco85@gmail.com>
+ */
+
+
+/**
+ * \file uan-animation.cc
+ * \ingroup uan
+ *
+ * This example showcases the "CW-MAC" described in System Design Considerations for Undersea Networks
+ * article in the IEEE Journal on Selected Areas of Communications 2008 by Nathan Parrish, Leonard Tracy
+ * and Sumit Roy. The MAC protocol is implemented in the class UanMacCw. CW-MAC is similar in nature
+ * to the IEEE 802.11 DCF with a constant backoff window. It requires two parameters to be set,
+ * the slot time and the contention window size. The contention window size is the backoff window
+ * size in slots, and the slot time is the duration of each slot. These parameters should be set
+ * according to the overall network size, internode spacing and the number of nodes in the network.
+ *
+ * This example deploys nodes randomly (according to RNG seed of course) in a finite square region with
+ * the X and Y coordinates of the nodes distributed uniformly. The CW parameter is varied throughout
+ * the simulation in order to show the variation in throughput with respect to changes in CW.
+ */
+
+#include "uan-animation.h"
+#include "ns3/core-module.h"
+#include "ns3/network-module.h"
+#include "ns3/netanim-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/tools-module.h"
+#include "ns3/applications-module.h"
+
+#include <fstream>
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("UanCwExample");
+
+NetAnimExperiment::NetAnimExperiment ()
+ : m_numNodes (15),
+ m_dataRate (80),
+ m_depth (70),
+ m_boundary (500),
+ m_packetSize (32),
+ m_bytesTotal (0),
+ m_cwMin (10),
+ m_cwMax (400),
+ m_cwStep (10),
+ m_avgs (3),
+ m_slotTime (Seconds (0.2)),
+ m_simTime (Seconds (1000))
+{
+}
+
+void
+NetAnimExperiment::ResetData ()
+{
+ NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Resetting data");
+ m_throughputs.push_back (m_bytesTotal * 8.0 / m_simTime.GetSeconds ());
+ m_bytesTotal = 0;
+}
+
+void
+NetAnimExperiment::IncrementCw (uint32_t cw)
+{
+ NS_ASSERT (m_throughputs.size () == m_avgs);
+
+ double avgThroughput = 0.0;
+ for (uint32_t i=0; i<m_avgs; i++)
+ {
+ avgThroughput += m_throughputs[i];
+ }
+ avgThroughput /= m_avgs;
+ m_throughputs.clear ();
+
+ Config::Set ("/NodeList/*/DeviceList/*/Mac/CW", UintegerValue (cw + m_cwStep));
+
+ SeedManager::SetRun (SeedManager::GetRun () + 1);
+
+ NS_LOG_DEBUG ("Average for cw=" << cw << " over " << m_avgs << " runs: " << avgThroughput);
+}
+void
+NetAnimExperiment::UpdatePositions (NodeContainer &nodes)
+{
+
+ NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Updating positions");
+ NodeContainer::Iterator it = nodes.Begin ();
+ UniformVariable uv (0, m_boundary);
+ for (; it != nodes.End (); it++)
+ {
+ Ptr<MobilityModel> mp = (*it)->GetObject<MobilityModel> ();
+ mp->SetPosition (Vector (uv.GetValue (), uv.GetValue (), 70.0));
+ }
+}
+
+void
+NetAnimExperiment::ReceivePacket (Ptr<Socket> socket)
+{
+ Ptr<Packet> packet;
+
+ while ((packet = socket->Recv ()))
+ {
+ m_bytesTotal += packet->GetSize ();
+ }
+ packet = 0;
+}
+
+void
+NetAnimExperiment::Run (UanHelper &uan)
+{
+ uan.SetMac ("ns3::UanMacCw", "CW", UintegerValue (m_cwMin), "SlotTime", TimeValue (m_slotTime));
+ NodeContainer nc = NodeContainer ();
+ NodeContainer sink = NodeContainer ();
+ nc.Create (m_numNodes);
+ sink.Create (1);
+
+ PacketSocketHelper socketHelper;
+ socketHelper.Install (nc);
+ socketHelper.Install (sink);
+
+#ifdef UAN_PROP_BH_INSTALLED
+ Ptr<UanPropModelBh> prop = CreateObjectWithAttributes<UanPropModelBh> ("ConfigFile", StringValue ("exbhconfig.cfg"));
+#else
+ Ptr<UanPropModelIdeal> prop = CreateObjectWithAttributes<UanPropModelIdeal> ();
+#endif //UAN_PROP_BH_INSTALLED
+ Ptr<UanChannel> channel = CreateObjectWithAttributes<UanChannel> ("PropagationModel", PointerValue (prop));
+
+ //Create net device and nodes with UanHelper
+ NetDeviceContainer devices = uan.Install (nc, channel);
+ NetDeviceContainer sinkdev = uan.Install (sink, channel);
+
+ MobilityHelper mobility;
+ Ptr<ListPositionAllocator> pos = CreateObject<ListPositionAllocator> ();
+
+ {
+ UniformVariable urv (0, m_boundary);
+ pos->Add (Vector (m_boundary / 2.0, m_boundary / 2.0, m_depth));
+ double rsum = 0;
+
+ double minr = 2 * m_boundary;
+ for (uint32_t i = 0; i < m_numNodes; i++)
+ {
+ double x = urv.GetValue ();
+ double y = urv.GetValue ();
+ double newr = sqrt ((x - m_boundary / 2.0) * (x - m_boundary / 2.0)
+ + (y - m_boundary / 2.0) * (y - m_boundary / 2.0));
+ rsum += newr;
+ minr = std::min (minr, newr);
+ pos->Add (Vector (x, y, m_depth));
+ }
+ NS_LOG_DEBUG ("Mean range from gateway: " << rsum / m_numNodes
+ << " min. range " << minr);
+
+ mobility.SetPositionAllocator (pos);
+ mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+ mobility.Install (sink);
+
+ NS_LOG_DEBUG ("Position of sink: "
+ << sink.Get (0)->GetObject<MobilityModel> ()->GetPosition ());
+ mobility.Install (nc);
+
+ PacketSocketAddress socket;
+ socket.SetSingleDevice (sinkdev.Get (0)->GetIfIndex ());
+ socket.SetPhysicalAddress (sinkdev.Get (0)->GetAddress ());
+ socket.SetProtocol (0);
+
+ OnOffHelper app ("ns3::PacketSocketFactory", Address (socket));
+ app.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+ app.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+ app.SetAttribute ("DataRate", DataRateValue (m_dataRate));
+ app.SetAttribute ("PacketSize", UintegerValue (m_packetSize));
+
+ ApplicationContainer apps = app.Install (nc);
+ apps.Start (Seconds (0.5));
+ Time nextEvent = Seconds (0.5);
+
+
+ for (uint32_t cw = m_cwMin; cw <= m_cwMax; cw += m_cwStep)
+ {
+
+ for (uint32_t an = 0; an < m_avgs; an++)
+ {
+ nextEvent += m_simTime;
+ Simulator::Schedule (nextEvent, &NetAnimExperiment::ResetData, this);
+ Simulator::Schedule (nextEvent, &NetAnimExperiment::UpdatePositions, this, nc);
+ }
+ Simulator::Schedule (nextEvent, &NetAnimExperiment::IncrementCw, this, cw);
+ }
+ apps.Stop (nextEvent + m_simTime);
+
+ Ptr<Node> sinkNode = sink.Get (0);
+ TypeId psfid = TypeId::LookupByName ("ns3::PacketSocketFactory");
+ if (sinkNode->GetObject<SocketFactory> (psfid) == 0)
+ {
+ Ptr<PacketSocketFactory> psf = CreateObject<PacketSocketFactory> ();
+ sinkNode->AggregateObject (psf);
+ }
+ Ptr<Socket> sinkSocket = Socket::CreateSocket (sinkNode, psfid);
+ sinkSocket->Bind (socket);
+ sinkSocket->SetRecvCallback (MakeCallback (&NetAnimExperiment::ReceivePacket, this));
+
+ m_bytesTotal = 0;
+
+ std::string traceFileName = "uan-animation.xml";
+ AnimationInterface anim(traceFileName.c_str ());
+
+ Simulator::Run ();
+ sinkNode = 0;
+ sinkSocket = 0;
+ pos = 0;
+ channel = 0;
+ prop = 0;
+ for (uint32_t i=0; i < nc.GetN (); i++)
+ {
+ nc.Get (i) = 0;
+ }
+ for (uint32_t i=0; i < sink.GetN (); i++)
+ {
+ sink.Get (i) = 0;
+ }
+
+ for (uint32_t i=0; i < devices.GetN (); i++)
+ {
+ devices.Get (i) = 0;
+ }
+ for (uint32_t i=0; i < sinkdev.GetN (); i++)
+ {
+ sinkdev.Get (i) = 0;
+ }
+
+ Simulator::Destroy ();
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+
+ LogComponentEnable ("UanCwExample", LOG_LEVEL_ALL);
+ LogComponentEnable ("AnimationInterface", LOG_LEVEL_ALL);
+
+ NetAnimExperiment exp;
+
+ std::string perModel = "ns3::UanPhyPerGenDefault";
+ std::string sinrModel = "ns3::UanPhyCalcSinrDefault";
+
+ CommandLine cmd;
+ cmd.AddValue ("NumNodes", "Number of transmitting nodes", exp.m_numNodes);
+ cmd.AddValue ("Depth", "Depth of transmitting and sink nodes", exp.m_depth);
+ cmd.AddValue ("RegionSize", "Size of boundary in meters", exp.m_boundary);
+ cmd.AddValue ("PacketSize", "Generated packet size in bytes", exp.m_packetSize);
+ cmd.AddValue ("DataRate", "DataRate in bps", exp.m_dataRate);
+ cmd.AddValue ("CwMin", "Min CW to simulate", exp.m_cwMin);
+ cmd.AddValue ("CwMax", "Max CW to simulate", exp.m_cwMax);
+ cmd.AddValue ("SlotTime", "Slot time duration", exp.m_slotTime);
+ cmd.AddValue ("Averages", "Number of topologies to test for each cw point", exp.m_avgs);
+ cmd.AddValue ("PerModel", "PER model name", perModel);
+ cmd.AddValue ("SinrModel", "SINR model name", sinrModel);
+ cmd.Parse (argc, argv);
+
+ ObjectFactory obf;
+ obf.SetTypeId (perModel);
+ Ptr<UanPhyPer> per = obf.Create<UanPhyPer> ();
+ obf.SetTypeId (sinrModel);
+ Ptr<UanPhyCalcSinr> sinr = obf.Create<UanPhyCalcSinr> ();
+
+ UanHelper uan;
+ UanTxMode mode;
+ mode = UanTxModeFactory::CreateMode (UanTxMode::FSK, exp.m_dataRate,
+ exp.m_dataRate, 12000,
+ exp.m_dataRate, 2,
+ "Default mode");
+ UanModesList myModes;
+ myModes.AppendMode (mode);
+
+ uan.SetPhy ("ns3::UanPhyGen",
+ "PerModel", PointerValue (per),
+ "SinrModel", PointerValue (sinr),
+ "SupportedModes", UanModesListValue (myModes));
+
+ exp.Run (uan);
+
+ per = 0;
+ sinr = 0;
+
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/netanim/examples/uan-animation.h Tue Jul 31 19:18:23 2012 +0200
@@ -0,0 +1,62 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Andrea Sacco
+ *
+ * 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: Andrea Sacco <andrea.sacco85@gmail.com>
+ */
+
+#ifndef UAN_CW_EXAMPLE_H
+#define UAN_CW_EXAMPLE_H
+
+#include "ns3/network-module.h"
+#include "ns3/tools-module.h"
+#include "ns3/uan-module.h"
+
+using namespace ns3;
+
+/**
+ * \class NetAnimExperiment
+ * \brief Helper class for UAN CW MAC example
+ *
+ */
+class NetAnimExperiment
+{
+public:
+ void Run (UanHelper &uan);
+ void ReceivePacket (Ptr<Socket> socket);
+ void UpdatePositions (NodeContainer &nodes);
+ void ResetData ();
+ void IncrementCw (uint32_t cw);
+ uint32_t m_numNodes;
+ uint32_t m_dataRate;
+ double m_depth;
+ double m_boundary;
+ uint32_t m_packetSize;
+ uint32_t m_bytesTotal;
+ uint32_t m_cwMin;
+ uint32_t m_cwMax;
+ uint32_t m_cwStep;
+ uint32_t m_avgs;
+
+ Time m_slotTime;
+ Time m_simTime;
+
+ std::vector<double> m_throughputs;
+
+ NetAnimExperiment ();
+};
+
+#endif /* UAN_CW_EXAMPLE_H */
--- a/src/netanim/examples/wscript Sun Jul 29 14:29:41 2012 +0200
+++ b/src/netanim/examples/wscript Tue Jul 31 19:18:23 2012 +0200
@@ -16,3 +16,7 @@
obj = bld.create_ns3_program('wireless-animation',
['netanim', 'applications', 'point-to-point', 'csma', 'wifi', 'mobility', 'network'])
obj.source = 'wireless-animation.cc'
+
+ obj = bld.create_ns3_program('uan-animation',
+ ['netanim', 'internet', 'mobility', 'tools', 'applications', 'uan'])
+ obj.source = 'uan-animation.cc'
--- a/src/netanim/helper/animation-interface-helper.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/netanim/helper/animation-interface-helper.h Tue Jul 31 19:18:23 2012 +0200
@@ -142,6 +142,7 @@
* \param fbTx First bit transmit time
* \param lbTx Last bit transmit time
* \param txLoc Transmitter Location
+ * \param txNodeId Tx Node Id if NetDevice is unknown
*
*/
AnimPacketInfo(Ptr <const NetDevice> tx_nd, const Time& fbTx, const Time& lbTx,Vector txLoc, uint32_t txNodeId = 0);
--- a/src/netanim/model/animation-interface.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/netanim/model/animation-interface.cc Tue Jul 31 19:18:23 2012 +0200
@@ -37,6 +37,8 @@
#include "ns3/constant-position-mobility-model.h"
#include "ns3/lte-ue-phy.h"
#include "ns3/lte-enb-phy.h"
+#include "ns3/uan-net-device.h"
+#include "ns3/uan-mac.h"
#include <stdio.h>
#include <unistd.h>
@@ -48,8 +50,6 @@
NS_LOG_COMPONENT_DEFINE ("AnimationInterface");
-
-
namespace ns3 {
#define PURGE_INTERVAL 5
@@ -161,6 +161,11 @@
return false;
}
+bool AnimationInterface::UanPacketIsPending (uint64_t AnimUid)
+{
+ return (m_pendingUanPackets.find (AnimUid) != m_pendingUanPackets.end ());
+}
+
bool AnimationInterface::WifiPacketIsPending (uint64_t AnimUid)
{
return (m_pendingWifiPackets.find (AnimUid) != m_pendingWifiPackets.end ());
@@ -547,6 +552,10 @@
MakeCallback (&AnimationInterface::CsmaPhyRxEndTrace, this));
Config::Connect ("/NodeList/*/DeviceList/*/$ns3::CsmaNetDevice/MacRx",
MakeCallback (&AnimationInterface::CsmaMacRxTrace, this));
+ Config::Connect ("/NodeList/*/DeviceList/*/$ns3::UanNetDevice/Phy/PhyTxBegin",
+ MakeCallback (&AnimationInterface::UanPhyGenTxTrace, this));
+ Config::Connect ("/NodeList/*/DeviceList/*/$ns3::UanNetDevice/Phy/PhyRxBegin",
+ MakeCallback (&AnimationInterface::UanPhyGenRxTrace, this));
ConnectLte ();
@@ -683,7 +692,7 @@
Ptr<NetDevice> tx, Ptr<NetDevice> rx,
Time txTime, Time rxTime)
{
- if (!m_started)
+ if (!m_started || !IsInTimeWindow ())
return;
NS_ASSERT (tx);
NS_ASSERT (rx);
@@ -729,6 +738,12 @@
NS_ASSERT (n);
return n->GetDevice (atoi (elements[3].c_str ()));
}
+
+void AnimationInterface::AddPendingUanPacket (uint64_t AnimUid, AnimPacketInfo &pktinfo)
+{
+ m_pendingUanPackets[AnimUid] = pktinfo;
+}
+
void AnimationInterface::AddPendingWifiPacket (uint64_t AnimUid, AnimPacketInfo &pktinfo)
{
@@ -778,6 +793,47 @@
}
}
+void AnimationInterface::UanPhyGenTxTrace (std::string context, Ptr<const Packet> p)
+{
+ if (!m_started || !IsInTimeWindow ())
+ return;
+ Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
+ NS_ASSERT (ndev);
+ Ptr <Node> n = ndev->GetNode ();
+ NS_ASSERT (n);
+ gAnimUid++;
+ NS_LOG_INFO ("Uan TxBeginTrace for packet:" << gAnimUid);
+ AnimByteTag tag;
+ tag.Set (gAnimUid);
+ p->AddByteTag (tag);
+ AnimPacketInfo pktinfo (ndev, Simulator::Now (), Simulator::Now (), UpdatePosition (n));
+ AddPendingUanPacket (gAnimUid, pktinfo);
+
+
+}
+
+void AnimationInterface::UanPhyGenRxTrace (std::string context, Ptr<const Packet> p)
+{
+ if (!m_started || !IsInTimeWindow ())
+ return;
+ Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
+ NS_ASSERT (ndev);
+ Ptr <Node> n = ndev->GetNode ();
+ NS_ASSERT (n);
+ uint64_t AnimUid = GetAnimUidFromPacket (p);
+ NS_LOG_INFO ("UanPhyGenRxTrace for packet:" << AnimUid);
+ if (!UanPacketIsPending (AnimUid))
+ {
+ NS_LOG_WARN ("UanPhyGenRxBeginTrace: unknown Uid");
+ return;
+ }
+ m_pendingUanPackets[AnimUid].ProcessRxBegin (ndev, Simulator::Now ());
+ m_pendingUanPackets[AnimUid].ProcessRxEnd (ndev, Simulator::Now (), UpdatePosition (n));
+ OutputWirelessPacket (p, m_pendingUanPackets[AnimUid], m_pendingUanPackets[AnimUid].GetRxInfo (ndev));
+
+}
+
+
void AnimationInterface::WifiPhyTxBeginTrace (std::string context,
Ptr<const Packet> p)
{
@@ -789,7 +845,7 @@
NS_ASSERT (n);
// Add a new pending wireless
gAnimUid++;
- NS_LOG_INFO ("TxBeginTrace for packet:" << gAnimUid);
+ NS_LOG_INFO ("Wifi TxBeginTrace for packet:" << gAnimUid);
AnimByteTag tag;
tag.Set (gAnimUid);
p->AddByteTag (tag);
@@ -833,7 +889,7 @@
Ptr <Node> n = ndev->GetNode ();
NS_ASSERT (n);
uint64_t AnimUid = GetAnimUidFromPacket (p);
- NS_LOG_INFO ("RxBeginTrace for packet:" << AnimUid);
+ NS_LOG_INFO ("Wifi RxBeginTrace for packet:" << AnimUid);
if (!WifiPacketIsPending (AnimUid))
{
NS_LOG_WARN ("WifiPhyRxBeginTrace: unknown Uid");
--- a/src/netanim/model/animation-interface.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/netanim/model/animation-interface.h Tue Jul 31 19:18:23 2012 +0200
@@ -36,6 +36,7 @@
#include "ns3/mac48-address.h"
#include "ns3/lte-ue-net-device.h"
#include "ns3/lte-enb-net-device.h"
+#include "ns3/uan-phy-gen.h"
namespace ns3 {
@@ -311,6 +312,11 @@
void LteSpectrumPhyRxStart (std::string context,
Ptr<const PacketBurst> pb);
+ void UanPhyGenTxTrace (std::string context,
+ Ptr<const Packet>);
+ void UanPhyGenRxTrace (std::string context,
+ Ptr<const Packet>);
+
void MobilityCourseChangeTrace (Ptr <const MobilityModel> mob);
// Write a string to the specified handle;
@@ -337,6 +343,10 @@
void AddPendingCsmaPacket (uint64_t AnimUid, AnimPacketInfo&);
bool CsmaPacketIsPending (uint64_t AnimUid);
+ std::map<uint64_t, AnimPacketInfo> m_pendingUanPackets;
+ void AddPendingUanPacket (uint64_t AnimUid, AnimPacketInfo&);
+ bool UanPacketIsPending (uint64_t AnimUid);
+
uint64_t GetAnimUidFromPacket (Ptr <const Packet>);
std::map<uint32_t, Vector> m_nodeLocation;
--- a/src/netanim/wscript Sun Jul 29 14:29:41 2012 +0200
+++ b/src/netanim/wscript Tue Jul 31 19:18:23 2012 +0200
@@ -7,8 +7,7 @@
def build (bld) :
- bld.install_files('${INCLUDEDIR}/%s%s/ns3' % (wutils.APPNAME, wutils.VERSION), '../../ns3/netanim-config.h')
- module = bld.create_ns3_module ('netanim', ['internet', 'mobility', 'wimax', 'wifi', 'csma', 'lte'])
+ module = bld.create_ns3_module ('netanim', ['internet', 'mobility', 'wimax', 'wifi', 'csma', 'lte', 'uan'])
module.includes = '.'
module.source = [
'model/animation-interface.cc',
@@ -29,8 +28,3 @@
if (bld.env['ENABLE_EXAMPLES']) :
bld.add_subdirs ('examples')
-def configure (conf) :
- conf.check (header_name='sys/socket.h', define_name='HAVE_SYS_SOCKET_H')
- conf.check (header_name='netinet/in.h', define_name='HAVE_NETINET_IN_H')
- conf.write_config_header ('ns3/netanim-config.h', top=True)
-
--- a/src/network/model/node.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/network/model/node.h Tue Jul 31 19:18:23 2012 +0200
@@ -57,14 +57,9 @@
public:
static TypeId GetTypeId (void);
- /**
- * Must be invoked by subclasses only.
- */
Node();
/**
* \param systemId a unique integer used for parallel simulations.
- *
- * Must be invoked by subclasses only.
*/
Node(uint32_t systemId);
Binary file src/olsr/test/bug780-0-0.pcap has changed
Binary file src/olsr/test/bug780-1-0.pcap has changed
Binary file src/olsr/test/bug780-2-0.pcap has changed
--- a/src/point-to-point/helper/point-to-point-helper.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/point-to-point/helper/point-to-point-helper.h Tue Jul 31 19:18:23 2012 +0200
@@ -170,6 +170,7 @@
* \param stream The output stream object to use when logging ascii traces.
* \param prefix Filename prefix to use for ascii trace files.
* \param nd Net device for which you want to enable tracing.
+ * \param explicitFilename Treat the prefix as an explicit filename if true
*/
virtual void EnableAsciiInternal (
Ptr<OutputStreamWrapper> stream,
--- a/src/spectrum/model/spectrum-value.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/spectrum/model/spectrum-value.cc Tue Jul 31 19:18:23 2012 +0200
@@ -388,19 +388,19 @@
}
double
-Integral (const SpectrumValue& x)
+Integral (const SpectrumValue& arg)
{
double i = 0;
- Values::const_iterator vit = x.ConstValuesBegin ();
- Bands::const_iterator bit = x.ConstBandsBegin ();
- while (vit != x.ConstValuesEnd ())
+ Values::const_iterator vit = arg.ConstValuesBegin ();
+ Bands::const_iterator bit = arg.ConstBandsBegin ();
+ while (vit != arg.ConstValuesEnd ())
{
- NS_ASSERT (bit != x.ConstBandsEnd ());
+ NS_ASSERT (bit != arg.ConstBandsEnd ());
i += (*vit) * (bit->fh - bit->fl);
++vit;
++bit;
}
- NS_ASSERT (bit == x.ConstBandsEnd ());
+ NS_ASSERT (bit == arg.ConstBandsEnd ());
return i;
}
--- a/src/spectrum/model/spectrum-value.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/spectrum/model/spectrum-value.h Tue Jul 31 19:18:23 2012 +0200
@@ -540,7 +540,7 @@
SpectrumValue Log10 (const SpectrumValue& arg);
SpectrumValue Log2 (const SpectrumValue& arg);
SpectrumValue Log (const SpectrumValue& arg);
-double Integral (const SpectrumValue& x);
+double Integral (const SpectrumValue& arg);
} // namespace ns3
--- a/src/uan/helper/acoustic-modem-energy-model-helper.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/uan/helper/acoustic-modem-energy-model-helper.h Tue Jul 31 19:18:23 2012 +0200
@@ -64,6 +64,7 @@
private:
/**
* \param device Pointer to the NetDevice to install DeviceEnergyModel.
+ * \param source Pointer to EnergySource installed on node.
*
* Implements DeviceEnergyModel::Install.
*/
--- a/src/uan/model/acoustic-modem-energy-model.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/uan/model/acoustic-modem-energy-model.h Tue Jul 31 19:18:23 2012 +0200
@@ -196,7 +196,7 @@
bool IsStateTransitionValid (const int destState);
/**
- * \param currentState New state the modem is currently in.
+ * \param state New state the modem is currently in.
*
* Sets current state. This function is private so that only the energy model
* can change its own state.
--- a/src/uan/model/uan-phy-gen.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/uan/model/uan-phy-gen.cc Tue Jul 31 19:18:23 2012 +0200
@@ -428,7 +428,7 @@
{
static TypeId tid = TypeId ("ns3::UanPhyGen")
- .SetParent<Object> ()
+ .SetParent<UanPhy> ()
.AddConstructor<UanPhyGen> ()
.AddAttribute ("CcaThreshold",
"Aggregate energy of incoming signals to move to CCA Busy state dB",
@@ -581,12 +581,14 @@
if (m_disabled)
{
NS_LOG_DEBUG ("Energy depleted, node cannot receive any packet. Dropping.");
+ NotifyRxDrop(pkt); // traced source netanim
return;
}
switch (m_state)
{
case TX:
+ NotifyRxDrop(pkt); // traced source netanim
NS_ASSERT (false);
break;
case RX:
@@ -595,6 +597,7 @@
double newSinrDb = CalculateSinrDb (m_pktRx, m_pktRxArrTime, m_rxRecvPwrDb, m_pktRxMode, m_pktRxPdp);
m_minRxSinrDb = (newSinrDb < m_minRxSinrDb) ? newSinrDb : m_minRxSinrDb;
NS_LOG_DEBUG ("PHY " << m_mac->GetAddress () << ": Starting RX in RX mode. SINR of pktRx = " << m_minRxSinrDb);
+ NotifyRxBegin(pkt); // traced source netanim
}
break;
@@ -623,6 +626,7 @@
{
m_state = RX;
UpdatePowerConsumption (RX);
+ NotifyRxBegin(pkt); // traced source netanim
m_rxRecvPwrDb = rxPowerDb;
m_minRxSinrDb = newsinr;
m_pktRx = pkt;
@@ -638,6 +642,7 @@
break;
case SLEEP:
NS_LOG_DEBUG ("Sleep mode. Dropping packet.");
+ NotifyRxDrop(pkt); // traced source netanim
break;
}
@@ -661,9 +666,11 @@
{
NS_LOG_DEBUG ("Sleep mode or dead. Dropping packet");
m_pktRx = 0;
+ NotifyRxDrop(pkt); // traced source netanim
return;
}
+ NotifyRxEnd(pkt); // traced source netanim
if (GetInterferenceDb ( (Ptr<Packet>) 0) > m_ccaThreshDb)
{
m_state = CCABUSY;
--- a/src/uan/model/uan-phy-gen.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/uan/model/uan-phy-gen.h Tue Jul 31 19:18:23 2012 +0200
@@ -241,7 +241,6 @@
TracedCallback<Ptr<const Packet>, double, UanTxMode > m_rxErrLogger;
TracedCallback<Ptr<const Packet>, double, UanTxMode > m_txLogger;
-
double CalculateSinrDb (Ptr<Packet> pkt, Time arrTime, double rxPowerDb, UanTxMode mode, UanPdp pdp);
double GetInterferenceDb (Ptr<Packet> pkt);
double DbToKp (double db);
--- a/src/uan/model/uan-phy.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/uan/model/uan-phy.cc Tue Jul 31 19:18:23 2012 +0200
@@ -69,8 +69,64 @@
TypeId UanPhy::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::UanPhy")
- .SetParent<Object> ();
+ .SetParent<Object> ()
+ .AddTraceSource ("PhyTxBegin",
+ "Trace source indicating a packet has begun transmitting over the channel medium",
+ MakeTraceSourceAccessor (&UanPhy::m_phyTxBeginTrace))
+ .AddTraceSource ("PhyTxEnd",
+ "Trace source indicating a packet has been completely transmitted over the channel.",
+ MakeTraceSourceAccessor (&UanPhy::m_phyTxEndTrace))
+ .AddTraceSource ("PhyTxDrop",
+ "Trace source indicating a packet has been dropped by the device during transmission",
+ MakeTraceSourceAccessor (&UanPhy::m_phyTxDropTrace))
+ .AddTraceSource ("PhyRxBegin",
+ "Trace source indicating a packet has begun being received from the channel medium by the device",
+ MakeTraceSourceAccessor (&UanPhy::m_phyRxBeginTrace))
+ .AddTraceSource ("PhyRxEnd",
+ "Trace source indicating a packet has been completely received from the channel medium by the device",
+ MakeTraceSourceAccessor (&UanPhy::m_phyRxEndTrace))
+ .AddTraceSource ("PhyRxDrop",
+ "Trace source indicating a packet has been dropped by the device during reception",
+ MakeTraceSourceAccessor (&UanPhy::m_phyRxDropTrace))
+ ;
return tid;
}
+
+void
+UanPhy::NotifyTxBegin (Ptr<const Packet> packet)
+{
+ m_phyTxBeginTrace (packet);
+}
+
+void
+UanPhy::NotifyTxEnd (Ptr<const Packet> packet)
+{
+ m_phyTxEndTrace (packet);
+}
+
+void
+UanPhy::NotifyTxDrop (Ptr<const Packet> packet)
+{
+ m_phyTxDropTrace (packet);
+}
+
+void
+UanPhy::NotifyRxBegin (Ptr<const Packet> packet)
+{
+ m_phyRxBeginTrace (packet);
+}
+
+void
+UanPhy::NotifyRxEnd (Ptr<const Packet> packet)
+{
+ m_phyRxEndTrace (packet);
+}
+
+void
+UanPhy::NotifyRxDrop (Ptr<const Packet> packet)
+{
+ m_phyRxDropTrace (packet);
+}
+
} // namespace ns3
--- a/src/uan/model/uan-phy.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/uan/model/uan-phy.h Tue Jul 31 19:18:23 2012 +0200
@@ -382,6 +382,91 @@
virtual void Clear (void) = 0;
virtual void SetSleepMode (bool sleep) = 0;
+
+
+ /**
+ * Public method used to fire a PhyTxBegin trace. Implemented for encapsulation
+ * purposes.
+ */
+ void NotifyTxBegin (Ptr<const Packet> packet);
+
+ /**
+ * Public method used to fire a PhyTxEnd trace. Implemented for encapsulation
+ * purposes.
+ */
+ void NotifyTxEnd (Ptr<const Packet> packet);
+
+ /**
+ * Public method used to fire a PhyTxDrop trace. Implemented for encapsulation
+ * purposes.
+ */
+ void NotifyTxDrop (Ptr<const Packet> packet);
+
+ /**
+ * Public method used to fire a PhyRxBegin trace. Implemented for encapsulation
+ * purposes.
+ */
+ void NotifyRxBegin (Ptr<const Packet> packet);
+
+ /**
+ * Public method used to fire a PhyRxEnd trace. Implemented for encapsulation
+ * purposes.
+ */
+ void NotifyRxEnd (Ptr<const Packet> packet);
+
+ /**
+ * Public method used to fire a PhyRxDrop trace. Implemented for encapsulation
+ * purposes.
+ */
+ void NotifyRxDrop (Ptr<const Packet> packet);
+
+private:
+ /**
+ * The trace source fired when a packet begins the transmission process on
+ * the medium.
+ *
+ * \see class CallBackTraceSource
+ */
+ TracedCallback<Ptr<const Packet> > m_phyTxBeginTrace;
+
+ /**
+ * The trace source fired when a packet ends the transmission process on
+ * the medium.
+ *
+ * \see class CallBackTraceSource
+ */
+ TracedCallback<Ptr<const Packet> > m_phyTxEndTrace;
+
+ /**
+ * The trace source fired when the phy layer drops a packet as it tries
+ * to transmit it.
+ *
+ * \see class CallBackTraceSource
+ */
+ TracedCallback<Ptr<const Packet> > m_phyTxDropTrace;
+
+ /**
+ * The trace source fired when a packet begins the reception process from
+ * the medium.
+ *
+ * \see class CallBackTraceSource
+ */
+ TracedCallback<Ptr<const Packet> > m_phyRxBeginTrace;
+
+ /**
+ * The trace source fired when a packet ends the reception process from
+ * the medium.
+ *
+ * \see class CallBackTraceSource
+ */
+ TracedCallback<Ptr<const Packet> > m_phyRxEndTrace;
+
+ /**
+ * The trace source fired when the phy layer drops a packet it has received.
+ *
+ * \see class CallBackTraceSource
+ */
+ TracedCallback<Ptr<const Packet> > m_phyRxDropTrace;
};
}
--- a/src/uan/model/uan-transducer-hd.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/uan/model/uan-transducer-hd.cc Tue Jul 31 19:18:23 2012 +0200
@@ -158,10 +158,12 @@
if (m_state == TX)
{
Simulator::Remove (m_endTxEvent);
+ src->NotifyTxDrop(packet); // traced source netanim
}
else
{
m_state = TX;
+ src->NotifyTxBegin(packet); // traced source netanim
}
@@ -185,6 +187,7 @@
m_endTxEvent = Simulator::Schedule (delay, &UanTransducerHd::EndTx, this);
m_endTxTime = Simulator::Now () + delay;
+ Simulator::Schedule(delay, &UanPhy::NotifyTxEnd, src, packet); // traced source netanim
}
void
--- a/src/wifi/helper/yans-wifi-helper.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/wifi/helper/yans-wifi-helper.h Tue Jul 31 19:18:23 2012 +0200
@@ -266,6 +266,7 @@
* \param stream The output stream object to use when logging ascii traces.
* \param prefix Filename prefix to use for ascii trace files.
* \param nd Net device for which you want to enable tracing.
+ * \param explicitFilename Treat the prefix as an explicit filename if true
*/
virtual void EnableAsciiInternal (Ptr<OutputStreamWrapper> stream,
std::string prefix,
--- a/src/wifi/model/wifi-phy.h Sun Jul 29 14:29:41 2012 +0200
+++ b/src/wifi/model/wifi-phy.h Tue Jul 31 19:18:23 2012 +0200
@@ -55,7 +55,7 @@
* whole packet. It means that we will report a BUSY status until
* one of the following happens:
* - NotifyRxEndOk
- * - NotifyExEndError
+ * - NotifyRxEndError
* - NotifyTxStart
*/
virtual void NotifyRxStart (Time duration) = 0;
--- a/src/wifi/test/dcf-manager-test.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/wifi/test/dcf-manager-test.cc Tue Jul 31 19:18:23 2012 +0200
@@ -85,7 +85,11 @@
uint64_t expectedGrantTime, uint32_t from);
void AddAccessRequestWithAckTimeout (uint64_t at, uint64_t txTime,
uint64_t expectedGrantTime, uint32_t from);
+ ///\param at time to schedule DoAccessRequest event
+ ///\param txTime DoAccessRequest txTime
+ ///\param expectedGrantTime DoAccessRequest expectedGrantTime
///\param ackDelay is delay of the ack after txEnd
+ ///\param from DoAccessRequest DcfStateTest
void AddAccessRequestWithSuccessfullAck (uint64_t at, uint64_t txTime,
uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from);
void DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime, DcfStateTest *state);
--- a/src/wifi/test/tx-duration-test.cc Sun Jul 29 14:29:41 2012 +0200
+++ b/src/wifi/test/tx-duration-test.cc Tue Jul 31 19:18:23 2012 +0200
@@ -43,7 +43,7 @@
*
* @param size size of payload in octets (includes everything after the PLCP header)
* @param payloadMode the WifiMode used
- * @param knownPlcpLengthFieldValue the known value of the Length field in the PLCP header
+ * @param knownDurationMicroSeconds the known payload size
*
* @return true if values correspond, false otherwise
*/
@@ -56,7 +56,7 @@
* @param size size of payload in octets (includes everything after the PLCP header)
* @param payloadMode the WifiMode used
* @param preamble the WifiPreamble used
- * @param knownPlcpLengthFieldValue the known value of the Length field in the PLCP header
+ * @param knownDurationMicroSeconds the known value of the transmission
*
* @return true if values correspond, false otherwise
*/