This file is indexed.

/usr/include/itpp/fixed/fix_base.h is in libitpp-dev 4.3.1-6.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

   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
1067
1068
/*!
 * \file
 * \brief Definitions of a base class for fixed-point data types
 * \author Johan Bergman
 *
 * -------------------------------------------------------------------------
 *
 * Copyright (C) 1995-2010  (see AUTHORS file for a list of contributors)
 *
 * This file is part of IT++ - a C++ library of mathematical, signal
 * processing, speech processing, and communications classes and functions.
 *
 * IT++ 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 3 of the License, or (at your option) any
 * later version.
 *
 * IT++ 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 IT++.  If not, see <http://www.gnu.org/licenses/>.
 *
 * -------------------------------------------------------------------------
 */

#ifndef FIX_BASE_H
#define FIX_BASE_H

#include <itpp/base/ittypes.h>
#include <itpp/stat/misc_stat.h>
#include <itpp/itexports.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 ITPP_EXPORT 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