# 3.2.1. Simulation parameters¶

The simulation parameters allow to customize the communication chain from an high level point of view. Various communication chain skeletons are available and can be selected as well as the channel code family to simulate, it is also possible to enable debug and benchmarking tools.

## 3.2.1.1. --sim-type¶

Type: text BFER BFERI BFER --sim-type BFERI

Select the type of simulation (or communication chain skeleton).

Description of the allowed values:

Value Description
BFER The standard BER/FER chain (Fig. 3.4).
BFERI The iterative BER/FER chain (Fig. 3.5).

Fig. 3.4 The standard BER/FER chain.

Fig. 3.5 The iterative BER/FER chain.

## 3.2.1.2. --sim-cde-type, -C¶

Type: text BCH LDPC POLAR POLAR_MK RA REP RS RSC RSC_DB TURBO TURBO_DB TURBO_PROD UNCODED -C BCH

Select the channel code family to simulate.

Description of the allowed values:

Value Description
BCH The Bose–Chaudhuri–Hocquenghem codes [BRC60].
LDPC The Low-Density Parity-Check codes [Gal63][MN95].
POLAR The Polar codes [Ari09].
POLAR_MK The Polar mono- or multi-kernel codes [BBGL17].
RA The Repeat Accumulate codes [DHJM98].
REP The Repetition codes [RL09].
RS The Reed-Solomon codes [RS60].
RSC The Recursive Systematic Convolutional codes [RL09].
RSC_DB The Recursive Systematic Convolutional codes with double binary symbols [RL09].
TURBO The Turbo codes [BGT93].
TURBO_DB The Turbo codes with double binary symbols [BGT93].
TURBO_PROD The Turbo Product codes [RL09].
UNCODED An uncoded simulation.

Note

Only POLAR, RSC, RSC_DB, LDPC and UNCODED codes are available in BFERI simulation type.

## 3.2.1.3. --sim-prec, -p¶

Type: integer 32 8 16 32 64 --sim-prec 8

Specify the representation of the real numbers in the receiver part of the chain.

64-bit and 32-bit precisions imply a floating-point representation of the real numbers. 16-bit and 8-bit imply a fixed-point representation of the real numbers (see the Quantizer parameters to configure the quantization).

Description of the allowed values:

Value Description
8 8-bit precision.
16 16-bit precision.
32 32-bit precision.
64 64-bit precision.

## 3.2.1.4. --sim-noise-type, -E¶

Type: text EBN0 ESN0 EP ROP EBN0 -E EBN0

Select the type of noise used to simulate.

Description of the allowed values:

Value Description
EBN0 SNR per information bit
ESN0 SNR per transmitted symbol
EP Event Probability
ROP Received Optical Power

ESN0 is automatically calculated from EBN0 and vice-versa with the following equation:

$$\frac{E_S}{N_0} = \frac{E_B}{N_0} + 10.\log(R.bps),$$

where $$R$$ is the bit rate and $$bps$$ the number of bits per symbol.

Note

When selecting EP the simulator runs in reverse order, ie. from the greatest event probability to the smallest one.

Hint

When selecting a BEC or BSC channel the EP noise type is automatically set except if you give another one. This is the same for the OPTICAL channel with the ROP noise type. The channel type is set with the --chn-type argument.

## 3.2.1.5. --sim-noise-min, -m¶

Type: real number -m 0.0

Set the minimal noise energy value to simulate.

Attention

This argument is another way to set the noise range to simulate. It is ignored or not required if the --sim-noise-range, -R argument is given, so you may find other piece of information in its description.

## 3.2.1.6. --sim-noise-max, -M¶

Type: real number -M 5.0

Set the maximal noise energy value to simulate.

Attention

This argument is another way to set the noise range to simulate. It is ignored or not required if the --sim-noise-range, -R argument is given, so you may find other piece of information in its description.

## 3.2.1.7. --sim-noise-step, -s¶

Type: real number 0.1 -s 1.0

Set the noise energy step between each simulation iteration.

Attention

This argument is another way to set the noise range to simulate. It is ignored or not required if the --sim-noise-range, -R argument is given, so you may find other piece of information in its description.

## 3.2.1.8. --sim-noise-range, -R¶

Type: MATLAB style vector step of 0.1 -R "0.5:1,1:0.05:1.2,1.21"

Set the noise energy range to run in a MATLAB style vector.

The above example will run the following noise points:

0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.05, 1.1, 1.15, 1.2, 1.21


Attention

The numerical range for a noise point is $$\left[-214.748; 213.952 \right]$$ with a precision of $$10^{-7}$$.

Note

If given, the --sim-noise-min, -m , --sim-noise-max, -M , and --sim-noise-step, -s parameters are ignored. But it is not required anymore if --sim-noise-min, -m and --sim-noise-max, -M are set.

## 3.2.1.9. --sim-pdf-path¶

Type: file read only --sim-pdf-path example/path/to/the/right/file

Give a file that contains PDF for different ROP.

To use with the OPTICAL channel. It sets the noise range from the given ones in the file. However, it is overwritten by --sim-noise-range, -R or limited by --sim-noise-min, -m and --sim-noise-max, -M with a minimum step of --sim-noise-step, -s between two values.

## 3.2.1.10. --sim-meta¶

Type: text --sim-meta "TITLE"

Add meta-data at the beginning of the AFF3CT standard output (INI format is used). The value of the parameter will be affected to the title meta-data and the command line will be added.

Note

PyBER, our GUI tool, can take advantage of those meta-data to enhance the display of the simulated curves.

## 3.2.1.11. --sim-coded¶

Enable the coded monitoring.

By default, in the simulation, the information bits are extracted from the decoded codewords and then they are compared to the initially generated information bits. When this parameter is enabled, the decoded codewords are directly compared with the initially encoded codewords.

Note

This parameter can have a negative impact on the BER performance.

Note

In some rare cases, to enable this parameter can reduce the simulation time.

## 3.2.1.12. --sim-coset, -c¶

Enable the coset approach.

The coset approach is a “trick” to simulate BER/FER performance without an encoder. It is based on the AZCW technique (see the --src-type parameter). In the specific case of modulation with memory effect, AZCWs can lead to erroneous BER/FER performance. The coset approach solves this problem by randomly generating N bits, those bits represent a frame but there are certainly not a codeword. Then, those random bits (or symbols) can be modulated avoiding AZCW unexpected effects. On the receiver side, the idea is to force the decoder to work on an AZCW (because the N received LLRs are not a valid codeword). Before the decoding process, knowing the initial bits sequence, when a bit is 1 then the corresponding input LLR is replaced by its opposite. This way, the decoder “believe” it is decoding an AZCW which is a valid codeword. After the decoding process, knowing the initial bits sequence, when a bit is 1, then the corresponding output bit is flipped.

## 3.2.1.13. --sim-dbg¶

Enable the debug mode. This print the input and the output frames after each task execution.

aff3ct -C "REP" -K 4 -N 8 -m 1.0 -M 1.0 --sim-dbg
# [...]
# Source_random::generate(int32 U_K[4])
# {OUT} U_K = [    1,     1,     0,     1]
# Returned status: 0
#
# Encoder_repetition_sys::encode(const int32 U_K[4], int32 X_N[8])
# {IN}  U_K = [    1,     1,     0,     1]
# {OUT} X_N = [    1,     1,     0,     1,     1,     1,     0,     1]
# Returned status: 0
#
# Modem_BPSK::modulate(const int32 X_N1[8], float32 X_N2[8])
# {IN}  X_N1 = [    1,     1,     0,     1,     1,     1,     0,     1]
# {OUT} X_N2 = [-1.00, -1.00,  1.00, -1.00, -1.00, -1.00,  1.00, -1.00]
# Returned status: 0
#
# Channel_AWGN_LLR::add_noise(const float32 X_N[8], float32 Y_N[8])
# {IN}  X_N = [-1.00, -1.00,  1.00, -1.00, -1.00, -1.00,  1.00, -1.00]
# {OUT} Y_N = [-0.29, -0.24,  1.55, -0.58, -0.33, -0.51,  0.80, -2.88]
# Returned status: 0
#
# Modem_BPSK::demodulate(const float32 Y_N1[8], float32 Y_N2[8])
# {IN}  Y_N1 = [-0.29, -0.24,  1.55, -0.58, -0.33, -0.51,  0.80, -2.88]
# {OUT} Y_N2 = [-0.73, -0.61,  3.91, -1.45, -0.84, -1.28,  2.01, -7.26]
# Returned status: 0
#
# Decoder_repetition_std::decode_siho(const float32 Y_N[8], int32 V_K[4])
# {IN}  Y_N = [-0.73, -0.61,  3.91, -1.45, -0.84, -1.28,  2.01, -7.26]
# {OUT} V_K = [    1,     1,     0,     1]
# Returned status: 0
#
# Monitor_BFER::check_errors(const int32 U[4], const int32 V[4])
# {IN}  U = [    1,     1,     0,     1]
# {IN}  V = [    1,     1,     0,     1]
# Returned status: 0
# [...]


Note

By default, the debug mode runs the simulation on one thread. It is strongly advise to remove the --sim-threads, -t parameter from your command line if you use it.

Hint

To limit the size of the debug trace, use the --mnt-max-fe, -e or --sim-max-fra, -n parameters to reduce the number of simulated frames. You may also think about using --sim-dbg-limit, -d when the frame size is too long to be display on a screen line.

## 3.2.1.14. --sim-dbg-hex¶

Enable the debug mode and print values in the hexadecimal format. This mode is useful for having a fully accurate representation of floating numbers.

aff3ct -C "REP" -K 4 -N 8 -m 1.0 -M 1.0 --sim-dbg-hex
# [...]
# Modem_BPSK::modulate(const int32 X_N1[8], float32 X_N2[8])
# {IN}  X_N1 = [0x1, 0x1, 0x0, 0x1, 0x1, 0x1, 0x0, 0x1]
# {OUT} X_N2 = [-0x1p+0, -0x1p+0, 0x1p+0, -0x1p+0, -0x1p+0, -0x1p+0, 0x1p+0, -0x1p+0]
# Returned status: 0
#
# Channel_AWGN_LLR::add_noise(const float32 X_N[8], float32 Y_N[8])
# {IN}  X_N = [-0x1p+0, -0x1p+0, 0x1p+0, -0x1p+0, -0x1p+0, -0x1p+0, 0x1p+0, -0x1p+0]
# {OUT} Y_N = [-0x1.28be1cp-2, -0x1.ec1ec8p-3, 0x1.8d242cp+0, -0x1.268a8p-1, -0x1.54c3ccp-2, -0x1.04df9ap-1, 0x1.9905f8p-1, -0x1.71132cp+1]
# Returned status: 0
# [...]


## 3.2.1.15. --sim-dbg-limit, -d¶

Type: integer 0 --sim-dbg-limit 1

Enable the debug mode and set the max number of elements to display per frame. 0 value means there is no dump limit.

aff3ct -C "REP" -K 4 -N 8 -m 1.0 -M 1.0 --sim-dbg-limit 3
# [...]
# Modem_BPSK::modulate(const int32 X_N1[8], float32 X_N2[8])
# {IN}  X_N1 = [    1,     1,     0, ...]
# {OUT} X_N2 = [-1.00, -1.00,  1.00, ...]
# Returned status: 0
#
# Channel_AWGN_LLR::add_noise(const float32 X_N[8], float32 Y_N[8])
# {IN}  X_N = [-1.00, -1.00,  1.00, ...]
# {OUT} Y_N = [-0.29, -0.24,  1.55, ...]
# Returned status: 0
# [...]


## 3.2.1.16. --sim-dbg-fra¶

Type: integer 0 --sim-dbg-fra 10

Enable the debug mode and set the max number of frames to display. 0 value means there is no frame limit. By default, a task works on one frame at a time.

This behavior can be overridden with the --sim-inter-fra, -F parameter and a task can be executed on many frames. In that case, you may want to reduce the number of displayed frames on screen:

aff3ct -C "REP" -K 4 -N 8 -m 1.0 -M 1.0 -F 8 --sim-dbg-fra 4
# [...]
# Modem_BPSK::modulate(const int32 X_N1[8x8], float32 X_N2[8x8])
# {IN}  X_N1 = [f1(    1,     1,     0,     1,     1,     1,     0,     1),
#               f2(    0,     1,     1,     0,     0,     1,     1,     0),
#               f3(    1,     0,     1,     1,     1,     0,     1,     1),
#               f4(    1,     0,     0,     0,     1,     0,     0,     0),
#               f5->f8:(...)]
# {OUT} X_N2 = [f1(-1.00, -1.00,  1.00, -1.00, -1.00, -1.00,  1.00, -1.00),
#               f2( 1.00, -1.00, -1.00,  1.00,  1.00, -1.00, -1.00,  1.00),
#               f3(-1.00,  1.00, -1.00, -1.00, -1.00,  1.00, -1.00, -1.00),
#               f4(-1.00,  1.00,  1.00,  1.00, -1.00,  1.00,  1.00,  1.00),
#               f5->f8:(...)]
# Returned status: 0
#
# Channel_AWGN_LLR::add_noise(const float32 X_N[8x8], float32 Y_N[8x8])
# {IN}  X_N = [f1(-1.00, -1.00,  1.00, -1.00, -1.00, -1.00,  1.00, -1.00),
#              f2( 1.00, -1.00, -1.00,  1.00,  1.00, -1.00, -1.00,  1.00),
#              f3(-1.00,  1.00, -1.00, -1.00, -1.00,  1.00, -1.00, -1.00),
#              f4(-1.00,  1.00,  1.00,  1.00, -1.00,  1.00,  1.00,  1.00),
#              f5->f8:(...)]
# {OUT} Y_N = [f1(-0.29, -0.24,  1.55, -0.58, -0.33, -0.51,  0.80, -2.88),
#              f2( 0.15, -0.71, -1.85,  1.69, -0.02, -0.50,  0.07,  0.79),
#              f3(-1.03,  1.39, -1.03, -2.03, -0.67,  0.91, -0.45, -0.88),
#              f4(-0.37, -1.07,  1.49,  0.94, -0.21,  1.35,  1.06,  0.97),
#              f5->f8:(...)]
# Returned status: 0
# [...]


## 3.2.1.17. --sim-dbg-prec¶

Type: integer 2 --sim-dbg-prec 1

Enable the debug mode and set the decimal precision (number of digits for the decimal part) of the floating-point elements.

aff3ct -C "REP" -K 4 -N 8 -m 1.0 -M 1.0 --sim-dbg-prec 4
# [...]
# Modem_BPSK::modulate(const int32 X_N1[8], float32 X_N2[8])
# {IN}  X_N1 = [      0,       0,       1,       1,       0,       0,       1,       1]
# {OUT} X_N2 = [ 1.0000,  1.0000, -1.0000, -1.0000,  1.0000,  1.0000, -1.0000, -1.0000]
# Returned status: 0
#
# Channel_AWGN_LLR::add_noise(const float32 X_N[8], float32 Y_N[8])
# {IN}  X_N = [ 1.0000,  1.0000, -1.0000, -1.0000,  1.0000,  1.0000, -1.0000, -1.0000]
# {OUT} Y_N = [ 1.4260,  0.4301, -1.5119,  0.1559,  0.0784,  1.6980, -1.6501, -0.0769]
# Returned status: 0
# [...]


## 3.2.1.18. --sim-seed, -S¶

Type: integer 0 --sim-seed 42

Set the PRNG seed used in the Monte Carlo simulation.

Note

AFF3CT uses PRNG to simulate the random. As a consequence the simulator behavior is reproducible from a run to another. It can be helpful to debug source code. However, when simulating in multi-threaded mode, the threads running order is not deterministic and so results will most likely be different from one execution to another.

## 3.2.1.19. --sim-stats¶

Display statistics for each task. Those statistics are shown after each simulated SNR point.

aff3ct -C "POLAR" -K 1723 -N 2048 -m 4.2 -M 4.2 -t 1 --sim-stats
# [...]
# -------------------------------------------||------------------------------||--------------------------------||--------------------------------
#        Statistics for the given task       ||       Basic statistics       ||       Measured throughput      ||        Measured latency
#     ('*' = any, '-' = same as previous)    ||          on the task         ||   considering the last socket  ||   considering the last socket
# -------------------------------------------||------------------------------||--------------------------------||--------------------------------
# -------------|-------------------|---------||----------|----------|--------||----------|----------|----------||----------|----------|----------
#       MODULE |              TASK |   TIMER ||    CALLS |     TIME |   PERC ||  AVERAGE |  MINIMUM |  MAXIMUM ||  AVERAGE |  MINIMUM |  MAXIMUM
#              |                   |         ||          |      (s) |    (%) ||   (Mb/s) |   (Mb/s) |   (Mb/s) ||     (us) |     (us) |     (us)
# -------------|-------------------|---------||----------|----------|--------||----------|----------|----------||----------|----------|----------
#      Channel |         add_noise |       * ||    14909 |     0.72 |  37.59 ||    42.17 |    20.75 |    45.52 ||    48.56 |    44.99 |    98.69
#       Source |          generate |       * ||    14909 |     0.60 |  31.13 ||    42.84 |     8.72 |    44.34 ||    40.22 |    38.86 |   197.63
#      Encoder |            encode |       * ||    14909 |     0.37 |  19.06 ||    83.17 |    16.00 |    86.10 ||    24.62 |    23.79 |   127.97
#      Decoder |       decode_siho |       * ||    14909 |     0.22 |  11.32 ||   117.80 |    36.67 |   126.75 ||    14.63 |    13.59 |    46.99
#      Monitor |      check_errors |       * ||    14909 |     0.01 |   0.42 ||  3186.81 |   120.63 |  3697.42 ||     0.54 |     0.47 |    14.28
#        Modem |        demodulate |       * ||    14909 |     0.00 |   0.25 ||  6350.57 |   160.24 |  7876.92 ||     0.32 |     0.26 |    12.78
#        Modem |          modulate |       * ||    14909 |     0.00 |   0.23 ||  6962.61 |   184.84 |  8291.50 ||     0.29 |     0.25 |    11.08
# -------------|-------------------|---------||----------|----------|--------||----------|----------|----------||----------|----------|----------
#        TOTAL |                 * |       * ||    14909 |     1.93 | 100.00 ||    13.34 |     3.38 |    14.10 ||   129.19 |   122.21 |   509.42
# [...]


Each line corresponds to a task. The tasks are sorted by execution time in the simulation (descending order). The first column group identifies the task:

• MODULE: the module type,
• TASK: the task name,
• TIMER: the name of the current task timer (it is possible to put timers inside a task to measure sub-parts of this task), * indicates that the whole task execution time is considered.

The second column group gives basic statistics:

• CALLS: the number of times this task has been executed,
• TIME: the cumulative time of all the task executions,
• PERC: the percentage of time taken by the task in the simulation.

The third column group shows the average, the minimum and the maximum throughputs. Those throughputs are calculated considering the size of the output frames. If the task does not have outputs (c.f the check_errors routine from the monitor) then the number of input bits is used instead. For instance, the encode task takes $$K$$ input bits and produces $$N$$ output bits, so $$N$$ bits will be considered in the throughput computations.

The last column group shows the average, the minimum and the maximum latencies.

The TOTAL line corresponds to the full communication chain. For the throughput computations, the last socket of the last task determines the number of considered bits. In a standard BER/FER simulation the last task is the check_errors routine from the monitor and consequently the number of information bits ($$K$$) is considered. However, if the --sim-coded parameter is enabled, it becomes the codeword size ($$N$$).

Note

Enabling the statistics can increase the simulation time due the measures overhead. This is especially true when short frames are simulated.

Warning

In multi-threaded mode the reported time is the cumulative time of all the threads. This time is bigger than the real simulation time because it does not consider that many tasks have been executed in parallel.

Warning

The task throughputs will not increase with the number of threads: the statistics consider the performance on one thread.

## 3.2.1.20. --sim-threads, -t¶

Type: integer 0 --sim-threads 1

Specify the number of threads used in the simulation. The 0 default value will automatically set the number of threads to the hardware number of threads available on the machine.

Note

Monte Carlo methods are known to be embarrassingly parallel, which is why, in most cases, the simulation throughput will increase linearly with the number of threads (unless this number exceeds the number of cores available). However, in some cases, especially for large frames, when the number of threads is high, the memory footprint can exceeds the size of the CPU caches and it becomes less interesting to use a large number of threads.

## 3.2.1.21. --sim-inter-fra, -F¶

Type: integer 1 --sim-inter-fra 3

Set the number of frames to process for each task execution.

The default behavior is to generate one frame at a time. This parameter enables to process more than one frame during the execution of a task.

The number of frames consumed and produced when a task is executed is called the inter frame level or IFL. Setting the IFL will automatically affect the IFL level in all the simulation modules (c.f. Fig. 3.6).

Fig. 3.6 3-way inter frame level in the communication chain.

The IFL also allows multi-user configurations to be simulated (see Fig. 3.7). This configurations is used when using SCMA modulation (see the --mdm-type SCMA parameter).

Fig. 3.7 3-way inter frame level with multi-user channel in the communication chain.

Note

For short frames, increase the IFL can increase the simulation throughput, it can hide task call overheads.

Note

For large frames, increase the IFL can decrease the simulation throughput due the CPU cache size limitation.

## 3.2.1.22. --sim-crc-earlyt¶

Enable to use the CRC to early terminate (if possible) the turbo decoding process. It should reduce the simulation time in high SNR zones.

Note

Available only for BFERI simulation type (c.f. the --sim-type parameter).

## 3.2.1.23. --sim-ite, -I¶

Type: integer 15 --sim-ite 10

Set the number of global iterations between the demodulator and the decoder.

Note

Available only for BFERI simulation type (c.f. the --sim-type parameter).

## 3.2.1.24. --sim-sequence-path¶

Type: file write sequence.dot --sim-sequence-path sequence.dot

Export the simulated sequence in Graphviz format at the given path.

## 3.2.1.25. --sim-max-fra, -n¶

Type: integer 0 --sim-max-fra 1

Set the maximum number of frames to simulate per noise point. When a noise point reaches the maximum frame limit, the simulation is stopped. 0 value means no limit.

Note

The default behavior is to stop the simulator when the limit is reached but it is possible to override it with the --sim-crit-nostop parameter. In this case, the remaining noise points will also be simulated and the limit will be applied for each of them.

## 3.2.1.26. --sim-stop-time¶

Type: integer 0 --sim-stop-time 1

Set the maximum time (in seconds) to simulate per noise point. When a noise point reaches the maximum time limit, the simulation is stopped. 0 value means no limit.

Note

The default behavior is to stop the simulator when the limit is reached but it is possible to override it with the --sim-crit-nostop parameter. In this case, the remaining noise points will also be simulated and the limit will be applied for each of them.

## 3.2.1.27. --sim-crit-nostop¶

Stop only the current noise point instead of the whole simulation.

To combine with the --sim-max-fra, -n and/or the --sim-stop-time parameters.

## 3.2.1.28. --sim-err-trk¶

Track the erroneous frames. When an error is found, the information bits from the source, the codeword from the encoder and the applied noise from the channel are dumped in several files.

Tip

When working on the design of a new decoder or when improving an existing one, it can be very interesting to have a database of erroneous frames to work on (especially if those errors occur at low BER/FER when the simulation time is important). This way it is possible to focus only on those erroneous frames and quickly see if the decoder improvements have an impact on them. It is also interesting to be able to easily extract the erroneous frames from the simulator to characterize the type of errors and better understand why the decoder fails.

Note

See the --sim-err-trk-rev argument to replay the erroneous dumped frames.

## 3.2.1.29. --sim-err-trk-rev¶

Replay dumped frames. By default this option reverts the --sim-err-trk parameter by replaying the erroneous frames that have been dumped.

Tip

To play back the erroneous frames, just add -rev to the --sim-err-trk argument and change nothing else to your command line.

## 3.2.1.30. --sim-err-trk-path¶

Type: file read/write error_tracker --sim-err-trk-path errors/err

Specify the base path for the --sim-err-trk and --sim-err-trk-rev parameters.

For the above example, the dumped or read files will be:

• errors/err_0.64.src
• errors/err_0.64.enc
• errors/err_0.64.chn

Note

For SNR noise type, the value used to define the filename is the noise variance $$\sigma$$.

Danger

Be careful, if you give a wrong path you will not have a warning message at the beginning of the simulation. It can be frustrating when running a very long simulation…

## 3.2.1.31. --sim-err-trk-thold¶

Type: integer 0 --sim-err-trk-thold 1

Specify a threshold value in number of erroneous bits before which a frame is dumped.

## 3.2.1.32. References¶

 [Ari09] E. Arikan. Channel polarization: a method for constructing capacity-achieving codes for symmetric binary-input memoryless channels. IEEE Transactions on Information Theory (TIT), 55(7):3051–3073, July 2009. doi:10.1109/TIT.2009.2021379.
 [BBGL17] M. Benammar, V. Bioglio, F. Gabry, and I. Land. Multi-kernel polar codes: proof of polarization and error exponents. In Information Theory Workshop (ITW), 101–105. IEEE, November 2017. doi:10.1109/ITW.2017.8277949.
 [BGT93] (1, 2) C. Berrou, A. Glavieux, and P. Thitimajshima. Near Shannon limit error-correcting coding and decoding: turbo-codes. In International Conference on Communications (ICC), volume 2, 1064–1070 vol.2. IEEE, May 1993. doi:10.1109/ICC.1993.397441.
 [BRC60] R.C. Bose and D.K. Ray-Chaudhuri. On a class of error correcting binary group codes. Springer Information and Control, 3(1):68 – 79, 1960. doi:10.1016/S0019-9958(60)90287-4.
 [DHJM98] D. Divsalar, H. Jin, and R. J. McEliece. Coding theorems for “turbo-like” codes. In Allerton Conference on Communication, Control and Computing, 201–210. September 1998. URL: https://pdfs.semanticscholar.org/b5cc/c94d4f9ea6df991190f17359ddd7ac47f005.pdf.
 [Gal63] R. G. Gallager. Low-density parity-check codes. 1963. URL: http://web.mit.edu/gallager/www/pages/ldpc.pdf.
 [MN95] D. J. C. MacKay and R. M. Neal. Good codes based on very sparse matrices. In IMA International Conference on Cryptography and Coding (IMA-CCC), 100–111. UK, December 1995. Springer. doi:10.1007/3-540-60693-9_13.
 [RS60] I. Reed and G. Solomon. Polynomial codes over certain finite fields. Journal of the Society for Industrial and Applied Mathematics, 8(2):300–304, 1960. doi:10.1137/0108018.
 [RL09] (1, 2, 3, 4) W. Ryan and S. Lin. Channel codes: classical and modern. Cambridge University Press, September 2009. ISBN 978-0-511-64182-4. URL: http://www.cambridge.org/9780521848688.