1 /* 2 * Copyright © 2004 Ondra Kamenik 3 * Copyright © 2019 Dynare Team 4 * 5 * This file is part of Dynare. 6 * 7 * Dynare is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * Dynare is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with Dynare. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 // Full symmetry tensor. 22 23 /* Here we define folded and unfolded tensors for full symmetry. All 24 tensors from here are identifying the multidimensional index with 25 columns. */ 26 27 #ifndef FS_TENSOR_H 28 #define FS_TENSOR_H 29 30 #include "tensor.hh" 31 #include "symmetry.hh" 32 #include "int_power.hh" 33 34 class FGSTensor; 35 class UGSTensor; 36 class FRSingleTensor; 37 class FSSparseTensor; 38 39 /* Folded tensor with full symmetry maintains only information about 40 number of symmetrical variables nv. Further, we implement what is 41 left from the super class FTensor. 42 43 We implement getOffset() which should be used with care since 44 its complexity. 45 46 We implement a method adding a given general symmetry tensor to the 47 full symmetry tensor supposing the variables of the general symmetry 48 tensor are stacked giving only one variable of the full symmetry 49 tensor. ⎛y⎞ 50 For instance, if x= ⎝u⎠, then we can add tensor [g_y²u] to tensor [g_x³]. 51 This is done in method addSubTensor(). Consult FGSTensor class declaration 52 to know what is general symmetry tensor. 53 54 Note that the past-the-end index is of the form (nv,…,nv), because 55 of the specific implementation of FFSTensor::increment(). 56 */ 57 58 class UFSTensor; 59 class FFSTensor : public FTensor 60 { 61 int nv; 62 public: 63 /* Constructs given the number of rows (explicit since the tensor is 64 column-oriented), the number of variables in each dimension, and the 65 number of dimensions */ FFSTensor(int r,int nvar,int d)66 FFSTensor(int r, int nvar, int d) 67 : FTensor(indor::along_col, IntSequence(d, nvar), 68 r, calcMaxOffset(nvar, d), d), 69 nv(nvar) 70 { 71 } 72 73 /* Constructs a tensor by one-dimensional contraction from the higher 74 dimensional tensor t. This is, it constructs a tensor 75 76 [g_yⁿ]_α₁…αₙ = [t_yⁿ⁺¹]_α₁…αₙβ [x]^β 77 78 See the implementation for details. */ 79 FFSTensor(const FFSTensor &t, const ConstVector &x); 80 81 /* Converts from sparse tensor (which is fully symmetric and folded by 82 nature). */ 83 explicit FFSTensor(const FSSparseTensor &t); 84 85 FFSTensor(const FFSTensor &) = default; 86 FFSTensor(FFSTensor &&) = default; 87 88 // Constructs from unfolded fully symmetric 89 explicit FFSTensor(const UFSTensor &ut); 90 91 // Constructs a subtensor of selected rows FFSTensor(int first_row,int num,FFSTensor & t)92 FFSTensor(int first_row, int num, FFSTensor &t) 93 : FTensor(first_row, num, t), nv(t.nv) 94 { 95 } 96 97 void increment(IntSequence &v) const override; 98 void decrement(IntSequence &v) const override; 99 std::unique_ptr<UTensor> unfold() const override; 100 Symmetry getSym() const101 getSym() const 102 { 103 return Symmetry{dimen()}; 104 } 105 106 int getOffset(const IntSequence &v) const override; 107 void addSubTensor(const FGSTensor &t); 108 int nvar() const109 nvar() const 110 { 111 return nv; 112 } 113 static int calcMaxOffset(int nvar, int d); 114 }; 115 116 /* Unfolded fully symmetric tensor is almost the same in structure as 117 FFSTensor, but the method unfoldData(). It takes columns which also 118 exist in folded version and copies them to all their symmetrical 119 locations. This is useful when constructing unfolded tensor from 120 folded one. */ 121 122 class UFSTensor : public UTensor 123 { 124 int nv; 125 public: UFSTensor(int r,int nvar,int d)126 UFSTensor(int r, int nvar, int d) 127 : UTensor(indor::along_col, IntSequence(d, nvar), 128 r, calcMaxOffset(nvar, d), d), 129 nv(nvar) 130 { 131 } 132 UFSTensor(const UFSTensor &t, const ConstVector &x); 133 UFSTensor(const UFSTensor &) = default; 134 UFSTensor(UFSTensor &&) = default; 135 explicit UFSTensor(const FFSTensor &ft); UFSTensor(int first_row,int num,UFSTensor & t)136 UFSTensor(int first_row, int num, UFSTensor &t) 137 : UTensor(first_row, num, t), nv(t.nv) 138 { 139 } 140 141 void increment(IntSequence &v) const override; 142 void decrement(IntSequence &v) const override; 143 std::unique_ptr<FTensor> fold() const override; 144 Symmetry getSym() const145 getSym() const 146 { 147 return Symmetry{dimen()}; 148 } 149 150 int getOffset(const IntSequence &v) const override; 151 void addSubTensor(const UGSTensor &t); 152 int nvar() const153 nvar() const 154 { 155 return nv; 156 } 157 static int calcMaxOffset(int nvar,int d)158 calcMaxOffset(int nvar, int d) 159 { 160 return power(nvar, d); 161 } 162 private: 163 void unfoldData(); 164 }; 165 166 #endif 167