File: fix_base.h

package info (click to toggle)
libitpp 4.0.4-2
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 7,520 kB
  • ctags: 6,341
  • sloc: cpp: 51,608; sh: 9,248; makefile: 636; fortran: 8
file content (1066 lines) | stat: -rw-r--r-- 45,735 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
/*!
 * \file
 * \brief Definitions of a base class for fixed-point data types
 * \author Johan Bergman
 *
 * -------------------------------------------------------------------------
 *
 * IT++ - C++ library of mathematical, signal processing, speech processing,
 *        and communications classes and functions
 *
 * Copyright (C) 1995-2008  (see AUTHORS file for a list of contributors)
 *
 * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
 *
 * -------------------------------------------------------------------------
 */

#ifndef FIX_BASE_H
#define FIX_BASE_H

#include <itpp/base/ittypes.h>
#include <itpp/stat/misc_stat.h>


namespace itpp {

  /*!
    \addtogroup fixed
    \brief Fixed-Point Data Types
    \author Johan Bergman

    \section fix_contents Contents

    <ul>
    <li> \ref fix_intro
    <li> \ref fix_base
    <ul>
    <li> \ref fix_base_shift
    <li> \ref fix_base_wordlen
    <li> \ref fix_base_emode
    <li> \ref fix_base_omode
    <li> \ref fix_base_qmode
    <li> \ref fix_base_stat
    <li> \ref fix_base_outputmode
    </ul>
    <li> \ref fix_real
    <li> \ref fix_complex
    <li> \ref fix_factory
    <li> \ref fix_ops
    <ul>
    <li> \ref fix_ops_asn
    <li> \ref fix_ops_add
    <li> \ref fix_ops_mult
    <li> \ref fix_ops_shift
    <li> \ref fix_ops_conv
    <li> \ref fix_ops_get
    <li> \ref fix_ops_io
    </ul>
    <li> \ref fix_fcn
    <ul>
    <li> \ref fix_fcn_isfix
    <li> \ref fix_fcn_setfix
    <li> \ref fix_fcn_shiftfix
    <li> \ref fix_fcn_assert
    <li> \ref fix_fcn_unfix
    <li> \ref fix_fcn_to
    <li> \ref fix_fcn_other
    </ul>
    </ul>

    \section fix_intro Introduction

    How to include the support for fixed-point data types in your program:
    \code
    #include <itpp/itbase.h>
    #include <itpp/itfixed.h>

    using namespace itpp;
    \endcode

    Fixed-point data types in IT++:
    <ul>
    <li> itpp::Fix (real-valued, restrictions specified as constructor arguments)
    <li> itpp::Fixed (real-valued, restrictions specified as template arguments)
    <li> itpp::CFix (complex-valued, restrictions specified as constructor arguments)
    <li> itpp::CFixed (complex-valued, restrictions specified as template arguments)
    </ul>

    These classes have a common base class called Fix_Base; see inheritance
    diagram in the itpp::Fix_Base documentation. The following data members are
    inherited from Fix_Base:
    <ul>
    <li> Shift factor
    <li> Word length
    <li> Sign encoding mode
    <li> Overflow mode
    <li> Quantization mode
    <li> Statistics object pointer
    <li> Output mode
    </ul>

    The term "fixed-point restrictions" refers to all these data members except
    for the shift factor, which is considered to be part of the "fixed-point
    number". The shift factor has some resemblance to a binary point. The value of
    the shift factor is set in initializations and assignments and it is modified
    by multiplications, divisions and bit-shifting operations. The shift factor is
    used for checking that both terms have been shifted the same amount in
    additions and subtractions. Also, it is used to "un-shift" the data when a
    fixed-point number is converted to floating point.

    Names of classes and enums have been aligned with the fixed-point data types
    in SystemC to some extent, but the fixed-point data types in IT++ and SystemC
    are quite different. In fact, the fixed-point data types in IT++ probably
    correspond better to the variable-precision integer types in SystemC (with
    one important difference: the fixed-point numbers in IT++ remember the amount
    of bit-shifting that has been applied to them, so that they can be converted
    back to "floating-point magnitude" easily if this is desired). The reason for
    this design choice in IT++ is to make the fixed-point simulations as fast as
    possible. If necessary, the core parts in itbase.h (e.g. Array, Vec and Mat)
    should be able to use some other data type than the ones presented here,
    assuming that a proper itpp::Factory is created for the data type, just like
    itpp::Fix_Factory has been created for these data types.

    Sometimes the documentation for the IT++ fixed-point data types states that
    a function is "useful in templated code". This means that the function
    facilitates writing templated code where the template argument is meant to be
    either a floating-point type (double or complex<double>) or a fixed-point type
    (Fix or CFix), i.e. code which is supposed to support both floating-point and
    fixed-point simulations. For example, the operator >>= is defined for Fix and
    CFix, but not for double and complex<double>, so it might be a better idea to
    use the function rshift_fix which is defined for Fix and CFix as well as
    double and complex<double>.

    For an example program, take a look at tests/fix_test.cpp.

    \section fix_base Fix_Base

    \subsection fix_base_shift Shift factor

    Supported shift factors: -64 ... +63 bit-shifts. 0 is \e default.

    An IT++ fixed-point number consists of a bit representation and a shift
    factor. The shift factor is a member of Fix_Base, while the bit representation
    is a member of the inherited class (Fix or CFix). The shift factor indicates
    the number of bit-shifts that have been performed on the data. A positive
    shift factor means that the data has been left-shifted while a negative shift
    factor means that the data has been right-shifted. For information about how
    the shift factor is affected by different operators, see section \ref fix_ops.

    \subsection fix_base_wordlen Word length

    Supported word lengths: 1 ... 64 bits. 64 is \e default.

    \warning Fix, Fixed, CFix and CFixed always use \e signed 64-bit integers to
    represent the fixed-point data. Therefore it is not recommended to declare
    variables with 64 bits and sign encoding mode US.

    \subsection fix_base_emode Sign encoding mode

    Supported sign encoding modes (itpp::e_mode):
    <ul>
    <li> TC (Two's complement)
    <li> US (Unsigned)
    </ul>

    TC is \e default.

    \warning Fix, Fixed, CFix and CFixed always use \e signed 64-bit integers to
    represent the fixed-point data. Therefore it is not recommended to declare
    variables with 64 bits and sign encoding mode US.

    \subsection fix_base_omode Overflow mode

    Supported overflow modes (itpp::o_mode):
    <ul>
    <li> SAT (Saturation)
    <li> WRAP (Wrap-around)
    </ul>

    WRAP is \e default.

    \note Fix, Fixed, CFix and CFixed apply this restriction during initialization
    and assignments only.

    \subsection fix_base_qmode Quantization mode

    Supported quantization modes (itpp::q_mode), with definitions borrowed from
    SystemC (see SystemC documentation for further details):
    <ul>
    <li> RND (Rounding to plus infinity): Add the most significant deleted bit to
    the remaining bits.
    <li> RND_ZERO (Rounding to zero): If the most significant deleted bit is 1,
    and either the sign bit or at least one other deleted bit is 1, add 1 to
    the remaining bits.
    <li> RND_MIN_INF (Rounding to minus infinity): If the most significant deleted
    bit is 1, and at least one other deleted bit is 1, add 1 to the remaining
    bits.
    <li> RND_INF (Rounding to infinity): If the most significant deleted bit is 1,
    and either the inverted value of the sign bit or at least one other
    deleted bit is 1, add 1 to the remaining bits.
    <li> RND_CONV (Convergent rounding with half-way value rounded to even value):
    If the most significant deleted bit is 1, and either the least
    significant of the remaining bits or at least one other deleted bit is 1,
    add 1 to the remaining bits.
    <li> RND_CONV_ODD (Convergent rounding with half-way value rounded to odd
    value): If the most significant deleted bit is 1, and either the least
    significant of the remaining bits is 0 or at least one other deleted bit
    is 1, add 1 to the remaining bits (not defined in SystemC).
    <li> TRN (Truncation): Just copy the remaining bits.
    <li> TRN_ZERO (Truncation to zero): If the sign bit is 1, and either the most
    significant deleted bit or at least one other deleted bit is 1, add 1 to
    the remaining bits.
    </ul>

    TRN is \e default. RND and TRN are usually the most implementation friendly.
    However, note that it is RND_INF that corresponds to "ordinary rounding" and
    TRN_ZERO that corresponds to "ordinary truncation".

    \note Fix, Fixed, CFix and CFixed apply this restriction during initialization
    and right-shift operations only.

    \subsection fix_base_stat Statistics object pointer

    Supported statistics object pointer values: either a pointer to an itpp::Stat
    object or 0. 0 is \e default.

    The sample method in the statistics object is called during initializations
    and assignments. A single statistics object can collect statistics from more
    than one fixed-point variable.

    \subsection fix_base_outputmode Output mode

    Supported output modes (itpp::output_mode), used by the output stream operator
    \<\<:
    <ul>
    <li> OUTPUT_FIX: Output fixed-point representation only
    <li> OUTPUT_FIX_SHIFT: Output fixed-point representation followed by \<shift\>
    <li> OUTPUT_FLOAT: Output floating-point value
    <li> OUTPUT_FLOAT_SHIFT: Output floating-point value followed by \<\<shift
    </ul>

    OUTPUT_FIX_SHIFT is \e default. Unlike the other modes, output_mode is a
    \e static data member of Fix_Base, i.e. the output_mode is common for all
    fixed-point variables. Use the following commands to change output_mode:
    \code
    Fix_Base::set_output_mode(OUTPUT_FIX);
    Fix_Base::set_output_mode(OUTPUT_FIX_SHIFT);
    Fix_Base::set_output_mode(OUTPUT_FLOAT);
    Fix_Base::set_output_mode(OUTPUT_FLOAT_SHIFT);

    // Alternative using a string parameter
    Fix_Base::set_output_mode("OUTPUT_FIX");
    Fix_Base::set_output_mode("OUTPUT_FIX_SHIFT");
    Fix_Base::set_output_mode("OUTPUT_FLOAT");
    Fix_Base::set_output_mode("OUTPUT_FLOAT_SHIFT");

    // Alternative using an ostream modifier
    cout << OUTPUT_FIX;
    cout << OUTPUT_FIX_SHIFT;
    cout << OUTPUT_FLOAT;
    cout << OUTPUT_FLOAT_SHIFT;
    \endcode

    \section fix_real Fix and Fixed

    Fix and Fixed are real-valued fixed-point data types primarily intended to
    replace \c double when a design is refined from floating- to fixed-point
    implementation. The data is stored in the least significant bits of a 64-bit
    integer variable.

    The following example shows how to declare a two's complement (i.e. a signed)
    20-bit variable with wrap-around as overflow handling with the initial value
    3.14 shifted up 10 bits:
    \code
    Fix a(3.14, 10, 20, TC, WRAP);
    Fixed<20, TC, WRAP> b(3.14, 10);
    \endcode

    Note that Fix takes the initial values as well as the fixed-point restrictions
    as constructor arguments. Fixed also takes the initial values as constructor
    arguments but it takes the fixed-point restrictions as template arguments.
    Choose Fix or Fixed depending on your needs. There are three main reasons why
    you would want to choose Fix instead of Fixed. First, if you want to change
    the fixed-point restrictions for a variable during run time, you have to use
    Fix, since the fixed-point restrictions for Fixed have been "fixed" at compile
    time. Second, if your code is using a lot of templating, you might end up with
    many more template arguments if you use Fixed than you would if you use Fix,
    since each set of fixed-point restrictions that you want to use will
    correspond to another type (based on the class template Fixed) instead of just
    different configurations of a single type (Fix). Third, the vector and matrix
    operations currently work better for Fix than for Fixed.

    \note Fixed is derived from Fix, which means that operators, methods and
    functions for Fix can be used for Fixed as well. However, the functions for
    Vec<Fix> (fixvec) and Mat<Fix> (fixmat) cannot be used for Vec<Fixed> and
    Mat<Fixed>.

    If you choose Fix, you should also read the section \ref fix_factory. If you
    choose Fixed, you may find it convenient to use the following typedefs:
    \code
    typedef Fixed<1, TC, WRAP> fixed1;  // for Fixed with 1 bit
    ...
    typedef Fixed<64, TC, WRAP> fixed64;  // for Fixed with 64 bits

    typedef Fixed<1, US, WRAP> ufixed1;  // for Unsigned Fixed with 1 bit
    ...
    typedef Fixed<64, US, WRAP> ufixed64;  // for Unsigned Fixed with 64 bits

    typedef Fixed<1, TC, SAT> sfixed1;  // for Saturated Fixed with 1 bit
    ...
    typedef Fixed<64, TC, SAT> sfixed64;  // for Saturated Fixed with 64 bits

    typedef Fixed<1, US, SAT> sufixed1;  // for Saturated Unsigned Fixed with 1 bit
    ...
    typedef Fixed<64, US, SAT> sufixed64;  // for Saturated Unsigned Fixed with 64 bits
    \endcode

    \note These typedefs use the default values for quantization mode (TRN) and
    statistics object pointer value (0). Also note that U stands for Unsigned but
    S stands for Saturated, NOT for Signed.

    Declaration corresponding to the above Fixed example but using one of the
    typedefs:
    \code
    fixed20 b(3.14, 10);
    \endcode

    \section fix_complex CFix and CFixed

    CFix and CFixed are complex-valued fixed-point data types primarily intended
    to replace <tt>complex<double></tt> when a design is refined from floating- to
    fixed-point implementation. The data is stored in the least significant bits
    of two 64-bit integer variables: one for the real part and one for the
    imaginary part. The two parts have a common shift factor (the one inherited
    from Fix_Base), so it is not possible to shift only one of them.

    The following example shows two ways to declare a two's complement (i.e. a
    signed) 20-bit variable with wrap-around as overflow handling with the initial
    value 1.11 + 2.22i shifted up 10 bits:
    \code
    CFix a(1.11, 2.22, 10, 20, TC, WRAP);
    CFixed<20, TC, WRAP> b(1.11, 2.22, 10);

    CFix c(complex<double>(1.11, 2.22), 0.0, 10, 20, TC, WRAP);
    CFixed<20, TC, WRAP> d(complex<double>(1.11, 2.22), 0.0, 10);
    \endcode

    \note The shift factor is passed as the third argument to the CFix/CFixed
    constructors. If the first argument is complex, the second argument is a
    dummy (that was set to 0.0 in the examples above).

    Choose CFix or CFixed depending on your needs; see section \ref fix_real. If
    you choose CFix, you should also read the section \ref fix_factory.
    \note CFixed is derived from CFix, which means that operators, methods and
    functions for CFix can be used for CFixed as well. However, the functions for
    Vec<CFix> (cfixvec) and Mat<CFix> (cfixmat) cannot be used for Vec<CFixed> and
    Mat<CFixed>.

    If you choose CFixed, you may find it convenient to use the following
    typedefs, which are predefined in IT++:
    \code
    typedef CFixed<1, TC, WRAP> cfixed1;  // for CFixed with 1 bit
    ...
    typedef CFixed<64, TC, WRAP> cfixed64;  // for CFixed with 64 bits

    typedef CFixed<1, TC, SAT> scfixed1;  // for Saturated CFixed with 1 bit
    ...
    typedef CFixed<64, TC, SAT> scfixed64;  // for Saturated CFixed with 64 bits
    \endcode

    \note These typedefs use the default values for sign encoding mode (TC),
    quantization mode (TRN) and statistics object pointer value (0). Also note
    that S stands for Saturated, NOT for Signed.

    Declarations corresponding to the above CFixed examples but using one of the
    typedefs:
    \code
    cfixed20 b(1.11, 2.22, 10);

    cfixed20 d(complex<double>(1.11, 2.22), 0.0, 10);
    \endcode

    \section fix_factory Fix_Factory

    IF you choose to use Fix/CFix (instead of Fixed/CFixed) AND you want to
    declare an Array/Vec/Mat with Fix/CFix elements AND you wish to specify
    some non-default fixed-point restrictions for these elements (i.e. something
    else than 64-bit word length, two's complement as sign encoding mode,
    wrap-around as overflow mode, truncation as quantization mode, and no
    statistics object), THEN you will need to use a Fix_Factory when declaring the
    Array/Vec/Mat of Fix/CFix. Here is how it works, somewhat simplified: you give
    the fixed-point restrictions as parameters to the Fix_Factory, then you give
    the Fix_Factory as a parameter to the Array/Vec/Mat, and finally the
    Array/Vec/Mat uses the Fix_Factory to create Fix/CFix elements with those
    fixed-point restrictions. All constructors for Array, Vec and Mat can take a
    Fix_Factory (or any other Factory for that matter) as their last, optional
    argument. It is assumed that all elements in the Array/Vec/Mat should have the
    same fixed-point restrictions (and use a common statistics object, if any).
    Note that a Fix_Factory can create both Fix and CFix objects. For information
    on Factory in general and Fix_Factory in particular, see the Detailed
    Descriptions for itpp::Factory and itpp::Fix_Factory, respectively.

    The following example shows how to declare a vector of length 7 with Fix
    elements that are two's complement 20-bit variables with wrap-around as
    overflow handling:
    \code
    Vec<Fix> a(7, FIX20);
    \endcode

    FIX20 is one of many predefined Fix_Factory; see the Detailed Description for
    itpp::Fix_Factory.

    \note One might wonder why the Array/Vec/Mat classes themselves cannot take
    the fixed-point restrictions as parameters directly and create the Fix/CFix
    elements without help from a Fix_Factory. The main benefit with the chosen
    solution is that the Array/Vec/Mat classes are not "contaminated" with
    knowledge (parameters, methods, etc) that is specific to the Fix/CFix types.
    If the user for some reason prefers to use some other type (i.e. a type not
    known by IT++) as the Array/Vec/Mat element type, this should work fine as
    long as he or she creates a corresponding Factory. And this is exactly the
    way that Fix/CFix and Fix_Factory work.

    Fix/CFix should not need to know about Fix_Factory, but for the sake of
    uniform syntax in declarations, an exception has been made:
    \code
    Fix a(FIX20);
    \endcode
    i.e. a Fix/CFix declaration can take a Fix_Factory as an argument, just like
    the Vec<Fix> declaration above did.

    \note All declarations with a Fix_Factory as a constructor argument also work
    in templated code; see the Detailed Description for itpp::Fix_Factory.

    \section fix_ops Operators and methods

    \subsection fix_ops_asn Initialization and assignment

    Fixed-point variables can be initialized with a fixed- or a floating-point
    value:
    \code
    // Initialize a with the floating-point value double(3.14*pow2(10))
    // and word length 20, two's complement, wrap-around and rounding
    Fix a(3.14, 10, 20, TC, WRAP, RND);

    // Initialize b with the fixed-point value a
    // and word length 7, two's complement, wrap-around and rounding
    Fix b(a, 7, TC, WRAP, RND);
    \endcode

    In this example, \c b was initialized with the same value as \c a but with
    smaller word length resulting in overflow, since round(3.14*pow2(10)) does not
    fit in the 7-bit variable \c b.

    \warning All fixed-point data types have default constructors. For Fix/CFix,
    the default constructor gives full word length (64 bits). If you call
    templated functions with Fix/CFix as the template argument, they might use
    these default constructors for declaration of temporary variables, which may
    then contain unrestricted (64-bit) temporary results. If you want these
    temporary results to be restricted, then you may have to modify the function
    to introduce fixed-point restrictions for the temporary results, and even
    introduce new temporary variables in order to avoid more than one operation
    per expression (demonstrated in an example below). For Fixed/CFixed, on the
    other hand, the default constructor gives certain fixed-point restrictions,
    but note that it may still be necessary to introduce other fixed-point
    restrictions as well as new temporary variables in the function.

    The assignment operators =, +=, -=, *=, /=, <<= and >>= are supported. For =,
    +=, -=, *= and /=, the right-hand operand can be another fixed-point variable
    or an integer value. If it is an integer value, it is interpreted as a
    fixed-point value with shift factor 0. The = operator simply copies the
    shift factor from the right side to the left side. For information on how the
    other operators treat the shift factor, see sections \ref fix_ops_add,
    \ref fix_ops_mult and \ref fix_ops_shift.

    If assignment to a scaled \c double is desired (when initialization has
    already taken place), the itpp::Fix::set method can be used.
    \code
    // Initialize c with the floating-point value double(3.14*pow2(10))
    // The shift factor is set to 10
    Fix c(3.14, 10);

    // Set c equal to 123. The shift factor is set to 0
    // Note that the old shift factor 10 is discarded
    c = 123;

    // Set c equal to the integer portion of double(3.14*pow2(10))
    // The shift factor is set to 10 (again)
    c.set(3.14, 10);

    // Achieve the same result using a temporary variable
    // Note that the assignment operator copies the shift factor
    c = Fix(3.14, 10);
    \endcode

    When the floating-point value is quantized, the quantization mode of the
    fixed-point variable (TRN in the example above, since \c c has this
    quantization mode) will be used, unless some other quantization mode (e.g.
    RND) is specified as a third argument to set:
    \code
    c.set(3.14, 10, RND);
    \endcode

    \note If you write templated code, you are better off if you use the set_fix
    function described in section \ref fix_fcn_setfix instead of the set method.

    There are also methods for setting data representation and shift directly:
    itpp::Fix::set_re, itpp::CFix::set_im and itpp::Fix_Base::set_shift. They are
    mainly intended for internal use.

    \subsection fix_ops_add Addition and subtraction

    Addition and subtraction between two fixed-point variables as well as between
    a fixed-point variable and an integer variable is supported. The unary minus
    operator is also defined. For Fix and CFix, several vector and matrix
    operations are also supported.
    \code
    // Declare a fixed-point vector with 7 elements
    // (using the predefined Fix_Factory FIX20)
    Vec<Fix> d(7, FIX20);

    // Set all 7 elements equal to 77 with shift factor 0
    d = Fix(77);

    // Declare an integer vector with 7 elements
    ivec e = "1 2 3 4 5 6 7";

    // Add fixed-point vector d and integer vector e. Both have shift factor 0
    Vec<Fix> f(d + e, FIX20);
    \endcode

    \note The addition and subtraction operators require that both operands have
    the same shift factor, unless at least one of the operands is zero. If \c d
    had been assigned with a different shift factor than 0 in the above example
    (and ASSERT_LEVEL > 0), the addition <tt>d + e</tt> would have failed,
    resulting in termination with the error message "assert_shifts: Different
    shifts not allowed!".

    As hinted earlier, the fixed-point restrictions are applied during
    initialization, assignment and bit-shifting operations only. This means that
    the result of an addition or subtraction is unrestricted (64 bits).
    \code
    Fix g(0, 0, 8, TC, SAT);
    Fix h(100, 0, 8, TC, SAT);
    Fix i(100, 0, 8, TC, SAT);
    Fix j(-100, 0, 8, TC, SAT);

    // The result of h + i is unrestricted (64 bits) but when it is assigned to g,
    // it is restricted according to the fixed-point restrictions of g (8 bits).
    // We get overflow, since 100+100=200 doesn't fit in an 8-bit signed variable.
    // The saturated result will be 127
    g = h + i;

    // But now we don't get overflow since 100+100-100=100 does fit!
    g = h + i + j;

    // If we do want the temporary result to be restricted, we have to make
    // an explicit temporary variable (with appropriate restrictions) for it
    Fix tmp(0, 0, 8, TC, SAT);
    // The first sum will be saturated to 127
    tmp = h + i;
    // The final sum will be 127-100=27, i.e. we got a different
    // result when we introduced a restricted temporary variable
    g = tmp + j;
    \endcode

    \subsection fix_ops_mult Multiplication and division

    Multiplication and division between two fixed-point variables as well as
    between a fixed-point variable and an integer variable is supported. For Fix
    and CFix, several vector and matrix operations are also supported.

    As stated earlier, the fixed-point restrictions are applied during
    initialization, assignment and bit-shifting operations only. This means that
    the result of a multiplication or division is unrestricted (64 bits) in the
    same way as for an addition or subtraction; see section \ref fix_ops_add.

    The resulting shift factor after a multiplication is the sum of the two shift
    factors, while the resulting shift factor after a division is the difference
    between the numerator shift factor and the denominator shift factor. The
    result of a division is always quantized using truncation, i.e. the
    quantization modes of the involved fixed-point variables do not matter. Note
    that sometimes divisions can be replaced with multiplications and/or
    bit-shifting operations; see section \ref fix_ops_shift.

    \warning Complex multiplications and divisions are supported, but they utilize
    temporary variables with full word length (64 bits).

    \subsection fix_ops_shift Bit-shifting

    The <<= and >>= operators are defined for the fixed-point data types. As an
    alternative, you can use the itpp::Fix::lshift and itpp::Fix::rshift methods.
    The appropriate fixed-point restrictions of the variable are applied, i.e.
    for left-shifting the overflow mode is applied and for right-shifting the
    quantization mode is applied. There is also a version of rshift that takes a
    quantization mode as the last argument (but there is no corresponding version
    of the >>= operator since it cannot take an extra argument).
    \code
    // Declare a fixed-point variable with the default quantization mode (TRN)
    Fix a(3.14, 10);

    // Right shift 5 bits using the quantization mode of a (i.e. TRN)
    a.rshift(5);

    // Right shift 5 bits using the specified quantization mode (i.e. RND)
    a.rshift(5, RND);
    \endcode

    \note If you write templated code, you are better off if you use the
    lshift_fix and rshift_fix functions described in section \ref fix_fcn_shiftfix
    instead of the <<= and >>= operators and the lshift and rshift methods.

    The << and >> operators are not defined for the fixed-point data types since
    it is not clear what quantization mode that should be applied for the >>
    operator.

    \subsection fix_ops_conv Conversion

    Fix and Fixed can be converted to double, while CFix and CFixed can be
    converted to complex<double>. The conversion operators "un-shift" the data by
    multiplying the fixed-point bit representation with pow2(-shift).

    The itpp::Fix::unfix and itpp::CFix::unfix methods can always be used:
    \code
    Fix a(3.14, 5);

    cout << a.unfix() << endl;
    \endcode
    The resulting output is 3.125.

    \note If you write templated code, you are better off if you use the
    functions unfix or to<T> described in sections \ref fix_fcn_unfix and
    \ref fix_fcn_to instead of the unfix method.

    Equivalently, the double(Fix&) and complex<double>(CFix&) operators can be
    used, unless you define NO_IMPLICIT_FIX_CONVERSION before you include IT++
    in your program.
    \code
    Fix a(3.14, 5);

    cout << double(a) << endl;
    \endcode
    The resulting output is 3.125.

    Finally, Fix/Fixed can be converted to CFix/CFixed using the appropriate
    CFix/CFixed constructors.

    \subsection fix_ops_get Get data members

    This example shows how to get the data members of fixed-point variables:
    \code
    Fix a;

    int64_t the_bit_representation = a.get_re();
    int the_shift_factor = a.get_shift();
    int the_word_length = a.get_wordlen();
    e_mode the_sign_encoding_mode = a.get_e_mode();
    o_mode the_overflow_mode = a.get_o_mode();
    q_mode the_quantization_mode = a.get_q_mode();

    int64_t max_bit_representation = a.get_max();
    int64_t min_bit_representation = a.get_min();
    \endcode

    \note For CFix and CFixed, you get the bit representation for the imaginary
    part with the method get_im().

    \subsection fix_ops_io Input and output

    The print() method outputs the entire state; see section \ref fix_ops_get.
    \code
    Fix a;
    a.print();
    \endcode

    This code example shows how to input and output fixed-point numbers:
    \code
    CFix a(FIX8);
    a.set(0.0, 0.0, 4);

    cout << "Old a: " << a << endl;
    cout << "New a? ";
    cin >> a;
    cout << "New a: " << a << endl;
    \endcode

    Complex numbers can be input on both the C++ form and the IT++ form:
    \code
    Old a: 0+0i<4>
    New a? 1+2i
    New a: 1+2i<4>
    \endcode
    \code
    Old a: 0+0i<4>
    New a? (1,2)
    New a: 1+2i<4>
    \endcode

    \note The output_mode is OUTPUT_FIX_SHIFT in these examples; see section
    \ref fix_base_outputmode.

    In the above examples, only the data representation was changed, while the
    shift (4) was kept. It is however possible to enter another (positive or
    negative) shift factor as well:
    \code
    Old a: 0+0i<4>
    New a? 1+2i<5>
    New a: 1+2i<5>
    \endcode

    It is also possible to enter a floating-point value and a (positive or
    negative) shift, rather than the data representation and a shift, if a
    slightly different format is used:
    \code
    Old a: 0+0i<4>
    New a? 1+2i<<5
    New a: 32+64i<5>
    \endcode

    The resulting data representation is the entered floating-point value 1+2i
    multiplied by 2^5.

    \note In order to enter a negative shift, write 1+2i<<-5. It is not possible
    to write 1+2i>>5.

    Vectors and matrices support the same formats for fixed-point numbers.
    However, all old elements are assumed to have the same shift factor, and the
    shift factor of the first old element becomes the default shift factor for all
    elements of the vector or matrix. The same holds in e.g. an Array of vectors,
    i.e. the shift factor of the first old element in each vector becomes the
    default shift factor for all elements of that vector. The default shift factor
    in an empty vector or matrix is zero.

    \section fix_fcn Functions

    \subsection fix_fcn_isfix Function is_fix

    The function itpp::is_fix returns true only if the argument is of type Fix or
    CFix or an Array/Vec/Mat of Fix or CFix.
    \code
    Array<Array<Vec<Fix> > > aavf(FIX20);
    bool will_be_true = is_fix(aavf);
    \endcode

    \warning Unfortunately, the function is_fix returns false if the argument is
    of type Fixed or CFixed.

    \subsection fix_fcn_setfix Function set_fix

    The function itpp::set_fix sets <tt>y = x * pow2(n)</tt> if the first argument
    is of type Fix or CFix or an Array/Vec/Mat of Fix or CFix. If the first
    argument is of type double or complex<double> or an Array/Vec/Mat of double or
    complex<double>, the function just sets <tt>y = x</tt>.
    \code
    Fix fix_var(FIX20);
    set_fix(fix_var, 3.14, 10);
    // fix_var will equal the integer portion of 3.14 * pow2(10)

    double double_var(FIX20);
    set_fix(double_var, 3.14, 10);
    // double_var will just equal 3.14
    \endcode

    When the floating-point value is quantized, the quantization mode of the first
    argument (TRN in the example above, since fix_var has this quantization mode)
    will be used, unless some other quantization mode (e.g. RND) is specified as a
    fourth argument to set_fix:
    \code
    set_fix(fix_var, 3.14, 10, RND);
    \endcode

    \subsection fix_fcn_shiftfix Functions lshift_fix and rshift_fix

    The functions itpp::lshift_fix and itpp::rshift_fix perform left and right
    bit-shifts, respectively, if the first argument is of type Fix or CFix or an
    Array/Vec/Mat of Fix or CFix. If the first argument is of type double or
    complex<double> or an Array/Vec/Mat of double or complex<double>, the
    functions do not do anything at all.
    \code
    // This will right-shift fix_var 10 bits
    rshift_fix(fix_var, 10);

    // This will not affect double_var
    rshift_fix(double_var, 10);
    \endcode

    When a fixed-point value is right-shifted using rshift_fix, the quantization
    mode of the first argument (TRN in the example above, since fix_var has this
    quantization mode) will be used, unless some other quantization mode (e.g.
    RND) is specified as a third argument to rshift_fix:
    \code
    rshift_fix(fix_var, 10, RND);
    \endcode

    When a fixed-point value is left-shifted using lshift_fix, on the other hand,
    the overflow mode of the first argument is always used.

    \subsection fix_fcn_assert Function assert_fixshift

    The itpp::assert_fixshift function can be used to verify that the shift factor
    has the expected value:
    \code
    Fix a(3.14, 5);

    // We will pass this check since 5 = 5
    assert_fixshift(a, 5);

    // The program will terminate (if ASSERT_LEVEL > 0) since 5 != 6
    assert_fixshift(a, 6);
    \endcode

    If the first argument is of type double or complex<double> instead, no test
    will be performed (since they have no shift factors).

    \subsection fix_fcn_unfix Function unfix

    The itpp::unfix function converts a fixed-point variable to a floating-point
    variable (or an Array/Vec/Mat of fixed-point variables to an Array/Vec/Mat of
    floating-point variables) by multiplying the fixed-point bit representation
    with pow2(-shift), using the unfix method mentioned above.
    \code
    Fix a(3.14, 5);
    double b = unfix(a);

    Array<Mat<CFix> > c(FIX40);
    cin >> c;
    Array<cmat> d = unfix(c);
    \endcode

    If the argument is a floating-point variable (or an Array/Vec/Mat of
    floating-point variables) instead, the function just returns the argument.

    \subsection fix_fcn_to Function to<T>

    The itpp::to<T> function is a very general conversion function. It converts a
    floating- or fixed-point variable to a floating- or fixed-point variable (or
    a floating- or fixed-point Array/Vec/Mat to a floating- or fixed-point
    Array/Vec/Mat) depending on the types of the argument and of the specified
    template parameter.
    \code
    // Convert a Vec<double> to a Vec<Fix> and assign it to f
    Vec<double> e = "1.0 2.0 3.0";
    Vec<Fix> f;
    f = to<Fix>(e);  // convert e "to Fix"

    // Convert an Array<Array<Mat<Fix> > > called g to
    // an Array<Array<Mat<CFix> > > and assign it to h
    Array<Array<Mat<CFix> > > h;
    h = to<CFix>(g);  // convert g "to CFix"
    \endcode

    \note The variants to<double>(x) and to<complex<double> >(x) provide the same
    functionality as unfix(x).

    \warning Be aware that the variants to<Fix>(x) and to<CFix>(x) will return
    a fixed-point variable with the shift factor(s) set to zero if x is a
    floating-point variable. However, if x is a fixed-point variable, the shift
    will be copied to the return variable.

    \subsection fix_fcn_other Other functions

    <ul>
    <li> itpp::abs
    <li> itpp::real
    <li> itpp::imag
    <li> itpp::conj
    </ul>
  */
  //!@{

  //! Representation for fixed-point data types
  typedef int64_t fixrep;
  //! Max word length
  const int MAX_WORDLEN = 64;

  //! Table for fast multiplication or division by 2^n
  const uint64_t UINT64_POW2[64] = {
    uint64_t(1),     uint64_t(1)<<1,  uint64_t(1)<<2,  uint64_t(1)<<3,  uint64_t(1)<<4,
    uint64_t(1)<<5,  uint64_t(1)<<6,  uint64_t(1)<<7,  uint64_t(1)<<8,  uint64_t(1)<<9,
    uint64_t(1)<<10, uint64_t(1)<<11, uint64_t(1)<<12, uint64_t(1)<<13, uint64_t(1)<<14,
    uint64_t(1)<<15, uint64_t(1)<<16, uint64_t(1)<<17, uint64_t(1)<<18, uint64_t(1)<<19,
    uint64_t(1)<<20, uint64_t(1)<<21, uint64_t(1)<<22, uint64_t(1)<<23, uint64_t(1)<<24,
    uint64_t(1)<<25, uint64_t(1)<<26, uint64_t(1)<<27, uint64_t(1)<<28, uint64_t(1)<<29,
    uint64_t(1)<<30, uint64_t(1)<<31, uint64_t(1)<<32, uint64_t(1)<<33, uint64_t(1)<<34,
    uint64_t(1)<<35, uint64_t(1)<<36, uint64_t(1)<<37, uint64_t(1)<<38, uint64_t(1)<<39,
    uint64_t(1)<<40, uint64_t(1)<<41, uint64_t(1)<<42, uint64_t(1)<<43, uint64_t(1)<<44,
    uint64_t(1)<<45, uint64_t(1)<<46, uint64_t(1)<<47, uint64_t(1)<<48, uint64_t(1)<<49,
    uint64_t(1)<<50, uint64_t(1)<<51, uint64_t(1)<<52, uint64_t(1)<<53, uint64_t(1)<<54,
    uint64_t(1)<<55, uint64_t(1)<<56, uint64_t(1)<<57, uint64_t(1)<<58, uint64_t(1)<<59,
    uint64_t(1)<<60, uint64_t(1)<<61, uint64_t(1)<<62, uint64_t(1)<<63
  };

  //! Table for fast multiplication by 2^(n-64)
  const double DOUBLE_POW2[128] = {
    0.5/UINT64_POW2[63], 1.0/UINT64_POW2[63], 1.0/UINT64_POW2[62], 1.0/UINT64_POW2[61],
    1.0/UINT64_POW2[60], 1.0/UINT64_POW2[59], 1.0/UINT64_POW2[58], 1.0/UINT64_POW2[57],
    1.0/UINT64_POW2[56], 1.0/UINT64_POW2[55], 1.0/UINT64_POW2[54], 1.0/UINT64_POW2[53],
    1.0/UINT64_POW2[52], 1.0/UINT64_POW2[51], 1.0/UINT64_POW2[50], 1.0/UINT64_POW2[49],
    1.0/UINT64_POW2[48], 1.0/UINT64_POW2[47], 1.0/UINT64_POW2[46], 1.0/UINT64_POW2[45],
    1.0/UINT64_POW2[44], 1.0/UINT64_POW2[43], 1.0/UINT64_POW2[42], 1.0/UINT64_POW2[41],
    1.0/UINT64_POW2[40], 1.0/UINT64_POW2[39], 1.0/UINT64_POW2[38], 1.0/UINT64_POW2[37],
    1.0/UINT64_POW2[36], 1.0/UINT64_POW2[35], 1.0/UINT64_POW2[34], 1.0/UINT64_POW2[33],
    1.0/UINT64_POW2[32], 1.0/UINT64_POW2[31], 1.0/UINT64_POW2[30], 1.0/UINT64_POW2[29],
    1.0/UINT64_POW2[28], 1.0/UINT64_POW2[27], 1.0/UINT64_POW2[26], 1.0/UINT64_POW2[25],
    1.0/UINT64_POW2[24], 1.0/UINT64_POW2[23], 1.0/UINT64_POW2[22], 1.0/UINT64_POW2[21],
    1.0/UINT64_POW2[20], 1.0/UINT64_POW2[19], 1.0/UINT64_POW2[18], 1.0/UINT64_POW2[17],
    1.0/UINT64_POW2[16], 1.0/UINT64_POW2[15], 1.0/UINT64_POW2[14], 1.0/UINT64_POW2[13],
    1.0/UINT64_POW2[12], 1.0/UINT64_POW2[11], 1.0/UINT64_POW2[10], 1.0/UINT64_POW2[9],
    1.0/UINT64_POW2[8],  1.0/UINT64_POW2[7],  1.0/UINT64_POW2[6],  1.0/UINT64_POW2[5],
    1.0/UINT64_POW2[4],  1.0/UINT64_POW2[3],  1.0/UINT64_POW2[2],  1.0/UINT64_POW2[1],
    1.0,                 1.0*UINT64_POW2[1],  1.0*UINT64_POW2[2],  1.0*UINT64_POW2[3],
    1.0*UINT64_POW2[4],  1.0*UINT64_POW2[5],  1.0*UINT64_POW2[6],  1.0*UINT64_POW2[7],
    1.0*UINT64_POW2[8],  1.0*UINT64_POW2[9],  1.0*UINT64_POW2[10], 1.0*UINT64_POW2[11],
    1.0*UINT64_POW2[12], 1.0*UINT64_POW2[13], 1.0*UINT64_POW2[14], 1.0*UINT64_POW2[15],
    1.0*UINT64_POW2[16], 1.0*UINT64_POW2[17], 1.0*UINT64_POW2[18], 1.0*UINT64_POW2[19],
    1.0*UINT64_POW2[20], 1.0*UINT64_POW2[21], 1.0*UINT64_POW2[22], 1.0*UINT64_POW2[23],
    1.0*UINT64_POW2[24], 1.0*UINT64_POW2[25], 1.0*UINT64_POW2[26], 1.0*UINT64_POW2[27],
    1.0*UINT64_POW2[28], 1.0*UINT64_POW2[29], 1.0*UINT64_POW2[30], 1.0*UINT64_POW2[31],
    1.0*UINT64_POW2[32], 1.0*UINT64_POW2[33], 1.0*UINT64_POW2[34], 1.0*UINT64_POW2[35],
    1.0*UINT64_POW2[36], 1.0*UINT64_POW2[37], 1.0*UINT64_POW2[38], 1.0*UINT64_POW2[39],
    1.0*UINT64_POW2[40], 1.0*UINT64_POW2[41], 1.0*UINT64_POW2[42], 1.0*UINT64_POW2[43],
    1.0*UINT64_POW2[44], 1.0*UINT64_POW2[45], 1.0*UINT64_POW2[46], 1.0*UINT64_POW2[47],
    1.0*UINT64_POW2[48], 1.0*UINT64_POW2[49], 1.0*UINT64_POW2[50], 1.0*UINT64_POW2[51],
    1.0*UINT64_POW2[52], 1.0*UINT64_POW2[53], 1.0*UINT64_POW2[54], 1.0*UINT64_POW2[55],
    1.0*UINT64_POW2[56], 1.0*UINT64_POW2[57], 1.0*UINT64_POW2[58], 1.0*UINT64_POW2[59],
    1.0*UINT64_POW2[60], 1.0*UINT64_POW2[61], 1.0*UINT64_POW2[62], 1.0*UINT64_POW2[63]
  };

  //! Sign encoding modes (aligned with SystemC)
  enum e_mode {
    TC,                 //!< Two's complement
    US                  //!< Unsigned
  };

  //! Overflow modes (aligned with SystemC)
  enum o_mode {
    SAT,                //!< Saturation
    SAT_ZERO,           //!< Saturation to zero (Not implemented)
    SAT_SYM,            //!< Symmetrical saturation (Not implemented)
    WRAP,               //!< Wrap-around
    WRAP_SM             //!< Sign magnitued wrap-around (Not implemented)
  };

  //! Quantization modes (aligned with SystemC)
  enum q_mode {
    RND,                //!< Rounding to plus infinity
    RND_ZERO,           //!< Rounding to zero
    RND_MIN_INF,        //!< Rounding to minus infinity
    RND_INF,            //!< Rounding to infinity
    RND_CONV,           //!< Convergent rounding with half-way value rounded to even value
    RND_CONV_ODD,       //!< Convergent rounding with half-way value rounded to odd value (not defined in SystemC)
    TRN,                //!< Truncation
    TRN_ZERO            //!< Truncation to zero
  };

  //! Output modes
  enum output_mode {
    OUTPUT_FIX,         //!< Output fixed-point representation only
    OUTPUT_FIX_SHIFT,   //!< Output fixed-point representation followed by \<shift\> (default)
    OUTPUT_FLOAT,       //!< Output floating-point value
    OUTPUT_FLOAT_SHIFT  //!< Output floating-point value followed by \<\<shift
  };

  /*!
    \brief Base class for fixed-point data types

    See the Detailed Description in the \ref fixed module.
  */
  class Fix_Base {
  public:
    //! Default constructor
    explicit Fix_Base(int s=0, int w=MAX_WORDLEN, e_mode e=TC, o_mode o=WRAP, q_mode q=TRN, Stat *ptr=0)
      : shift(s), wordlen(w), emode(e), omode(o), qmode(q), stat_ptr(ptr) {init();}
    //! Copy constructor
    Fix_Base(const Fix_Base &x)
      : shift(x.shift), wordlen(MAX_WORDLEN), emode(TC), omode(WRAP), qmode(TRN), stat_ptr(0) {init();}
    //! Destructor
    virtual ~Fix_Base() {}

    //! Set shift (without shifting)
    void set_shift(int s) {shift = s;}
    //! Set output mode to OUTPUT_FIX, OUTPUT_FIX_SHIFT, OUTPUT_FLOAT or OUTPUT_FLOAT_SHIFT. Static member function.
    static void set_output_mode(output_mode o) {outputmode = o;}
    //! Set output mode to "OUTPUT_FIX", "OUTPUT_FIX_SHIFT", "OUTPUT_FLOAT" or "OUTPUT_FLOAT_SHIFT". Static member function.
    static void set_output_mode(std::string o);

    //! Get shift
    int get_shift() const {return shift;}
    //! Get word length
    int get_wordlen() const {return wordlen;}
    //! Get sign encoding mode
    e_mode get_e_mode() const {return emode;}
    //! Get overflow mode
    o_mode get_o_mode() const {return omode;}
    //! Get quantization mode
    q_mode get_q_mode() const {return qmode;}
    //! Get output mode
    output_mode get_output_mode() const {return outputmode;}
    //! Get maximum value of data representation
    fixrep get_max() const {return max;}
    //! Get minimum value of data representation
    fixrep get_min() const {return min;}
    //! Print restrictions
    virtual void print() const;

  protected:
    //! Accumulated bitshift (positive means left-shifted, negative means right-shifted)
    int shift;
    //! Word length
    int wordlen;
    //! Sign encoding mode
    e_mode emode;
    //! Overflow mode
    o_mode omode;
    //! Quantization mode
    q_mode qmode;
    //! Pointer to statistics object
    Stat *stat_ptr;
    //! Minimum allowed value (help variable to speed up calculations)
    fixrep min;
    //! Maximum allowed value (help variable to speed up calculations)
    fixrep max;
    //! Number of unused (MSB) bits (help variable to speed up calculations)
    int n_unused_bits;

    //! Calculate help variables min, max and n_unused_bits
    void init();
    //! Handle overflows using overflow mode \c omode and make call to statistics object (if any)
    fixrep apply_o_mode(fixrep x) const;
    //! Convert from \c double to \c fixrep using \c shift and quantization mode \c qmode, then call <tt>limit()</tt>
    fixrep scale_and_apply_modes(double x) const {return scale_and_apply_modes(x, qmode);}
    //! Convert from \c double to \c fixrep using \c shift and quantization mode \c q, then call <tt>limit()</tt>
    fixrep scale_and_apply_modes(double x, q_mode q) const;
    //! Right shift \c n bits using quantization mode \c qmode and make call to statistics object (if any)
    fixrep rshift_and_apply_q_mode(fixrep x, int n) const {return rshift_and_apply_q_mode(x, n, qmode);}
    //! Right shift \c n bits using quantization mode \c q and make call to statistics object (if any)
    fixrep rshift_and_apply_q_mode(fixrep x, int n, q_mode q) const;

  private:
    //! Output mode
    static output_mode outputmode;
  };

  //! Set output mode
  inline std::ostream &operator<<(std::ostream &os, const output_mode &o)
  {
    Fix_Base::set_output_mode(o);
    return os;
  }

  //!@}

} // namespace itpp

#endif // #ifndef FIX_BASE_H