1 /*
2    CheMPS2: a spin-adapted implementation of DMRG for ab initio quantum chemistry
3    Copyright (C) 2013-2018 Sebastian Wouters
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License along
16    with this program; if not, write to the Free Software Foundation, Inc.,
17    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 #ifndef SPECIAL_CHEMPS2_H
21 #define SPECIAL_CHEMPS2_H
22 
23 namespace CheMPS2{
24 /** Special class.
25     \author Sebastian Wouters <sebastianwouters@gmail.com>
26     \date April 7, 2016
27 
28     The special class contains static special functions used at various places throughout the code. */
29    class Special{
30 
31       public:
32 
33          //! Phase function
34          /** \param power_times_two Two times the power of the phase (-1)^{ power }
35              \return The phase (-1)^{ power_times_two / 2 } */
phase(const int power_times_two)36          static int phase( const int power_times_two ){ return (((( power_times_two / 2 ) % 2 ) != 0 ) ? -1 : 1 ); }
37 
38          //! Triangle function for two variables
39          /** \param global The triangle counter global = i + ( j * ( j + 1 ) ) / 2 with i <= j
40              \param result Integer array of size 2 where to store i <= j */
invert_triangle_two(const int global,int * result)41          static void invert_triangle_two( const int global, int * result ){
42 
43             int j = 0;
44             while ((( j + 1 ) * ( j + 2 )) <= ( 2 * global )){ j++; }
45             result[ 1 ] = j;
46             result[ 0 ] = global - ( j * ( j + 1 ) ) / 2;
47 
48          }
49 
50          //! LOWER triangle function for two variables
51          /** \param global The lower triangle counter global = i + ( j * ( j - 1 ) ) / 2 with i < j
52              \param result Integer array of size 2 where to store i < j */
invert_lower_triangle_two(const int global,int * result)53          static void invert_lower_triangle_two( const int global, int * result ){
54 
55             int j = 1;
56             while (( j * ( j + 1 )) <= ( 2 * global )){ j++; }
57             result[ 1 ] = j;
58             result[ 0 ] = global - ( j * ( j - 1 ) ) / 2;
59 
60          }
61 
62          //! Triangle function for three variables
63          /** \param global The triangle counter global = i + ( j * ( j + 1 ) ) / 2 + ( k * ( k + 1 ) * ( k + 2 ) ) / 6 with i <= j <= k
64              \param result Integer array of size 3 where to store i <= j <= k */
invert_triangle_three(const int global,int * result)65          static void invert_triangle_three( const int global, int * result ){
66 
67             int k = 0;
68             while ((( k + 1 ) * ( k + 2 ) * ( k + 3 )) <= ( 6 * global )){ k++; }
69             const int remainder = global - ( k * ( k + 1 ) * ( k + 2 ) ) / 6;
70             int j = 0;
71             while ((( j + 1 ) * ( j + 2 )) <= ( 2 * remainder )){ j++; }
72             result[ 2 ] = k;
73             result[ 1 ] = j;
74             result[ 0 ] = remainder - ( j * ( j + 1 ) ) / 2;
75 
76          }
77 
78    };
79 }
80 
81 #endif
82