ctf.hpp 28.7 KB
Newer Older
1 2
/*Copyright (c) 2011, Edgar Solomonik, all rights reserved.*/

3 4
#ifndef _tCTF_HPP_
#define _tCTF_HPP_
5 6 7 8

#include "mpi.h"
#include <stdio.h>
#include <stdint.h>
9
#include <vector>
10 11
#include "../src/dist_tensor/cyclopstf.hpp"

Edgar Solomonik's avatar
Edgar Solomonik committed
12 13 14 15 16 17 18 19 20 21 22 23 24 25
/**
 * labels corresponding to symmetry of each tensor dimension
 * NS = 0 - nonsymmetric
 * SY = 1 - symmetric
 * AS = 2 - antisymmetric
 * SH = 3 - symmetric hollow
 */
#if (!defined NS && !defined SY && !defined SH)
#define NS 0
#define SY 1
#define AS 2
#define SH 3
#endif

26
typedef long_int lont_int;
solomon's avatar
solomon committed
27

Edgar Solomonik's avatar
Edgar Solomonik committed
28 29 30 31 32 33
/**
 * \brief reduction types for tensor data (enum actually defined in ../src/dist_tensor/cyclopstf.hpp)
 */
//enum CTF_OP { CTF_OP_SUM, CTF_OP_SUMABS, CTF_OP_SQNRM2,
//              CTF_OP_MAX, CTF_OP_MIN, CTF_OP_MAXABS, CTF_OP_MINABS };

34 35 36 37 38 39 40 41 42 43
/* custom element-wise function for tensor scale */
template<typename dtype>
class tCTF_fscl {
  public:
    /**
     * \brief function signature for element-wise scale operation
     * \param[in] alpha scaling value, defined in scale call 
     *            but subject to internal change due to symmetry
     * \param[in,out] a element from tensor A
     **/
44 45
    void  (*func_ptr)(dtype   alpha, 
                      dtype & a);
46 47 48 49 50 51 52 53 54 55 56 57 58 59
  public:
    tCTF_fscl() { func_ptr = NULL; }
};
/* custom element-wise function for tensor sum */
template<typename dtype>
class tCTF_fsum {
  public:
    /**
     * \brief function signature for element-wise summation operation
     * \param[in] alpha scaling value, defined in summation call 
     *            but subject to internal change due to symmetry
     * \param[in] a element from summand tensor A
     * \param[in,out] b element from summand tensor B
     **/
60 61 62
    void  (*func_ptr)(dtype   alpha, 
                      dtype   a,
                      dtype  &b);
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
  public:
    tCTF_fsum() { func_ptr = NULL; }
};
/* custom element-wise function for tensor contraction */
template<typename dtype>
class tCTF_fctr {
  public:
    /**
     * \brief function signature for element-wise contraction operation
     * \param[in] alpha scaling value, defined in contraction call 
     *            but subject to internal change due to symmetry
     * \param[in] a element from contraction tensor A
     * \param[in] b element from contraction tensor B
     * \param[in,out] c element from contraction tensor C
     **/
78 79 80 81
    void  (*func_ptr)(dtype  alpha, 
                      dtype  a, 
                      dtype  b,
                      dtype &c);
82 83 84 85
  public:
    tCTF_fctr() { func_ptr = NULL; }
};

86
/**
87
 * \brief an instance of the tCTF library (world) on a MPI communicator
88
 */
89 90
template<typename dtype>
class tCTF_World {
91 92
  public:
    MPI_Comm comm;
93
    tCTF<dtype> * ctf;
94 95 96

  public:
    /**
97 98 99 100 101
     * \brief creates tCTF library on comm_ that can output profile data 
     *        into a file with a name based on the main args
     * \param[in] comm_ MPI communicator associated with this CTF instance
     * \param[in] argc number of main arguments 
     * \param[in] argv main arguments 
102
     */
103
    tCTF_World(int argc, char * const * argv);
104

105
    /**
106 107 108 109 110
     * \brief creates tCTF library on comm_ that can output profile data 
     *        into a file with a name based on the main args
     * \param[in] comm_ MPI communicator associated with this CTF instance
     * \param[in] argc number of main arguments 
     * \param[in] argv main arguments 
111
     */
112
    tCTF_World(MPI_Comm       comm_ = MPI_COMM_WORLD,
113
               int            argc = 0,
114
               char * const * argv = NULL);
115 116

    /**
117
     * \brief creates tCTF library on comm_
Edgar Solomonik's avatar
Edgar Solomonik committed
118 119
     * \param[in] ndim number of torus network dimensions
     * \param[in] lens lengths of torus network dimensions
120
     * \param[in] comm MPI global context for this CTF World
121 122
     * \param[in] argc number of main arguments 
     * \param[in] argv main arguments 
123
     */
124
    tCTF_World(int            ndim, 
125 126
               int const *    lens, 
               MPI_Comm       comm_ = MPI_COMM_WORLD,
127
               int            argc = 0,
128
               char * const * argv = NULL);
129 130

    /**
131
     * \brief frees tCTF library
132
     */
133
    ~tCTF_World();
134 135
};

136 137 138
template<typename dtype>
class tCTF_Idx_Tensor;

139 140 141
template<typename dtype>
class tCTF_Sparse_Tensor;

142
/**
143
 * \brief an instance of a tensor within a tCTF world
144
 */
145 146
template<typename dtype>
class tCTF_Tensor {
147
  public:
148 149
    int tid, ndim;
    int * sym, * len;
150
    char * idx_map;
151
    char const * name;
152
    tCTF_Tensor * ctr_nbr;
153
    tCTF_World<dtype> * world;
154 155

  public:
156 157 158 159 160
    /**
     * \breif default constructor sets nothing 
     */
    tCTF_Tensor(){};

161 162
    /**
     * \brief copies a tensor (setting data to zero or copying A)
Edgar Solomonik's avatar
Edgar Solomonik committed
163 164
     * \param[in] A tensor to copy
     * \param[in] copy whether to copy the data of A into the new tensor
165
     */
Edgar Solomonik's avatar
Edgar Solomonik committed
166
    tCTF_Tensor(tCTF_Tensor const &   A,
167
                bool                  copy = true);
168 169 170

    /**
     * \brief copies a tensor filled with zeros
Edgar Solomonik's avatar
Edgar Solomonik committed
171 172 173 174
     * \param[in] ndim number of dimensions of tensor
     * \param[in] len edge lengths of tensor
     * \param[in] sym symmetries of tensor (e.g. symmetric matrix -> sym={SY, NS})
     * \param[in] world_ a world for the tensor to live in
175 176
     * \param[in] name an optionary name for the tensor
     * \param[in] profile set to 1 to profile contractions involving this tensor
177
     */
178
    tCTF_Tensor(int                  ndim_,
Edgar Solomonik's avatar
Edgar Solomonik committed
179 180
                int const *          len_,
                int const *          sym_,
181 182
                tCTF_World<dtype> &  world_,
                char const *         name_ = NULL,
183
                int                  profile_ = 0);
184 185 186 187 188 189 190
    
    /**
     * \brief gives the values associated with any set of indices
     * \param[in] npair number of values to fetch
     * \param[in] global_idx index within global tensor of each value to fetch
     * \param[in,out] data a prealloced pointer to the data with the specified indices
     */
191 192 193
    void read(long_int          npair, 
              long_int const *  global_idx, 
              dtype *           data) const;
194
    
195 196 197 198 199
    /**
     * \brief gives the values associated with any set of indices
     * \param[in] npair number of values to fetch
     * \param[in,out] pairs a prealloced pointer to key-value pairs
     */
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
    void read(long_int          npair,
              tkv_pair<dtype> * pairs) const;
    
    /**
     * \brief sparse add: A[global_idx[i]] = alpha*A[global_idx[i]]+beta*data[i]
     * \param[in] npair number of values to read into tensor
     * \param[in] alpha scaling factor on read data
     * \param[in] beta scaling factor on value in initial values vector
     * \param[in] global_idx global index within tensor of value to add
     * \param[in] data values to add to the tensor
     */
    void read(long_int         npair, 
              dtype            alpha, 
              dtype            beta,
              long_int const * global_idx,
              dtype *          data) const;

    /**
     * \brief sparse read: pairs[i].d = alpha*A[pairs[i].k]+beta*pairs[i].d
     * \param[in] npair number of values to read into tensor
     * \param[in] alpha scaling factor on read data
     * \param[in] beta scaling factor on value in initial pairs vector
     * \param[in] pairs key-value pairs to add to the tensor
     */
    void read(long_int          npair,
              dtype             alpha,
              dtype             beta,
              tkv_pair<dtype> * pairs) const;
   
229

230 231 232 233 234 235
    /**
     * \brief writes in values associated with any set of indices
     * \param[in] npair number of values to write into tensor
     * \param[in] global_idx global index within tensor of value to write
     * \param[in] data values to  write to the indices
     */
236 237 238
    void write(long_int         npair, 
               long_int const * global_idx, 
               dtype const    * data);
239 240 241 242 243 244

    /**
     * \brief writes in values associated with any set of indices
     * \param[in] npair number of values to write into tensor
     * \param[in] pairs key-value pairs to write to the tensor
     */
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
    void write(long_int                 npair,
               tkv_pair<dtype> const *  pairs);
    
    /**
     * \brief sparse add: A[global_idx[i]] = beta*A[global_idx[i]]+alpha*data[i]
     * \param[in] npair number of values to write into tensor
     * \param[in] alpha scaling factor on value to add
     * \param[in] beta scaling factor on original data
     * \param[in] global_idx global index within tensor of value to add
     * \param[in] data values to add to the tensor
     */
    void write(long_int         npair, 
               dtype            alpha, 
               dtype            beta,
               long_int const * global_idx,
               dtype const *    data);

    /**
     * \brief sparse add: A[pairs[i].k] = alpha*A[pairs[i].k]+beta*pairs[i].d
     * \param[in] npair number of values to write into tensor
     * \param[in] alpha scaling factor on value to add
     * \param[in] beta scaling factor on original data
     * \param[in] pairs key-value pairs to add to the tensor
     */
    void write(long_int                npair,
               dtype                   alpha,
               dtype                   beta,
               tkv_pair<dtype> const * pairs);
273 274 275
   
    /**
     * \brief contracts C[idx_C] = beta*C[idx_C] + alpha*A[idx_A]*B[idx_B]
276
     *        if fseq defined computes fseq(alpha,A[idx_A],B[idx_B],beta*C[idx_C])
Edgar Solomonik's avatar
Edgar Solomonik committed
277 278 279 280 281 282 283
     * \param[in] alpha A*B scaling factor
     * \param[in] A first operand tensor
     * \param[in] idx_A indices of A in contraction, e.g. "ik" -> A_{ik}
     * \param[in] B second operand tensor
     * \param[in] idx_B indices of B in contraction, e.g. "kj" -> B_{kj}
     * \param[in] beta C scaling factor
     * \param[in] idx_C indices of C (this tensor),  e.g. "ij" -> C_{ij}
284 285
     * \param[in] fseq sequential operation to execute, default is multiply-add
     */
286
    void contract(dtype                    alpha, 
287 288 289 290
                  const tCTF_Tensor&       A, 
                  char const *             idx_A,
                  const tCTF_Tensor&       B, 
                  char const *             idx_B,
291
                  dtype                    beta,
292 293 294
                  char const *             idx_C,
                  tCTF_fctr<dtype>         fseq = tCTF_fctr<dtype>());
    
295 296
    /**
     * \brief sums B[idx_B] = beta*B[idx_B] + alpha*A[idx_A]
297
     *        if fseq defined computes fseq(alpha,A[idx_A],beta*B[idx_B])
Edgar Solomonik's avatar
Edgar Solomonik committed
298 299 300 301 302
     * \param[in] alpha A scaling factor
     * \param[in] A first operand tensor
     * \param[in] idx_A indices of A in sum, e.g. "ij" -> A_{ij}
     * \param[in] beta B scaling factor
     * \param[in] idx_B indices of B (this tensor), e.g. "ij" -> B_{ij}
303 304
     * \param[in] fseq sequential operation to execute, default is multiply-add
     */
305
    void sum(dtype                   alpha, 
306 307
             const tCTF_Tensor&      A, 
             char const *            idx_A,
308
             dtype                   beta,
309 310
             char const *            idx_B,
             tCTF_fsum<dtype>        fseq = tCTF_fsum<dtype>());
311 312 313
    
    /**
     * \brief scales A[idx_A] = alpha*A[idx_A]
314 315 316 317
     *        if fseq defined computes fseq(alpha,A[idx_A])
     * \param[in] alpha A scaling factor
     * \param[in] idx_A indices of A (this tensor), e.g. "ij" -> A_{ij}
     * \param[in] fseq sequential operation to execute, default is multiply-add
318
     */
319
    void scale(dtype                   alpha, 
320 321
               char const *            idx_A,
               tCTF_fscl<dtype>        fseq = tCTF_fscl<dtype>());
322

323 324 325 326 327 328 329 330 331
    /**
     * \brief cuts out a slice (block) of this tensor A[offsets,ends)
     * \param[in] offsets bottom left corner of block
     * \param[in] ends top right corner of block
     * \return new tensor corresponding to requested slice
     */
    tCTF_Tensor slice(int const * offsets,
                      int const * ends);
    
332 333 334
    tCTF_Tensor slice(long_int corner_off,
                      long_int corner_end);
    
335 336 337 338 339 340 341 342 343 344
    /**
     * \brief cuts out a slice (block) of this tensor A[offsets,ends)
     * \param[in] offsets bottom left corner of block
     * \param[in] ends top right corner of block
     * \return new tensor corresponding to requested slice which lives on
     *          oworld
     */
    tCTF_Tensor slice(int const *         offsets,
                      int const *         ends,
                      tCTF_World<dtype> * oworld);
345 346 347 348

    tCTF_Tensor slice(long_int            corner_off,
                      long_int            corner_end,
                      tCTF_World<dtype> * oworld);
349 350
    
    
351 352 353 354 355 356 357 358 359 360
    /**
     * \brief cuts out a slice (block) of this tensor = B
     *   B[offsets,ends)=beta*B[offsets,ends) + alpha*A[offsets_A,ends_A)
     * \param[in] offsets bottom left corner of block
     * \param[in] ends top right corner of block
     * \param[in] alpha scaling factor of this tensor
     * \param[in] offsets bottom left corner of block of A
     * \param[in] ends top right corner of block of A
     * \param[in] alpha scaling factor of tensor A
     */
361 362 363 364 365 366 367
    void slice(int const *    offsets,
               int const *    ends,
               dtype          beta,
               tCTF_Tensor &  A,
               int const *    offsets_A,
               int const *    ends_A,
               dtype          alpha);
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
    void slice(long_int       corner_off,
               long_int       corner_end,
               dtype          beta,
               tCTF_Tensor &  A,
               long_int       corner_off_A,
               long_int       corner_end_A,
               dtype          alpha);

    /**
     * \brief TODO: apply permutation to matrix, potentially extracting a slice
     *              B[perms_B[0][i],perms_B[0][j],...] 
     *                = beta*B[...] + alpha*A[perms_A[0][i],perms_A[1][j],...]
     *
     * \param[in] perms_B specifies permutations for tensor B, e.g. B[perms_B[0][i],perms_B[1][j]]
     *                    if NULL then no permutation applied, if a subarray NULL, a permutation
     *                    will be applied only if it is defined for a previous index in the symmetric
     *                    index group to which the NULL subarray index belongs
     * \param[in] beta scaling factor for values of tensor B (this)
     * \param[in] A specification of operand tensor A
     * \param[in] perms_A see description of perms_B, mentally performing %s/B/A/g
     * \param[in] alpha scaling factor for A tensor
     */
    /*void permute(int const **   perms_B,
                 dtype          beta,
                 tCTF_Tensor &  A,
                 int const **   perms_A,
                 dtype          alpha);*/
396

Edgar Solomonik's avatar
Edgar Solomonik committed
397 398 399 400
    /**
     * \brief aligns data mapping with tensor A
     * \param[in] A align with this tensor
     */
401
    void align(tCTF_Tensor const & A);
Edgar Solomonik's avatar
Edgar Solomonik committed
402

403 404
    /**
     * \brief performs a reduction on the tensor
405
     * \param[in] op reduction operation (see top of this cyclopstf.hpp for choices)
406
     */    
407
    dtype reduce(CTF_OP op);
408 409
    
    /**
410
     * \brief computes the entrywise 1-norm of the tensor
411 412 413 414
     */    
    dtype norm1(){ return reduce(CTF_OP_NORM1); };

    /**
415
     * \brief computes the frobenius norm of the tensor
416 417 418 419
     */    
    dtype norm2(){ return reduce(CTF_OP_NORM2); };

    /**
420
     * \brief finds the max absolute value element of the tensor
421 422
     */    
    dtype norm_infty(){ return reduce(CTF_OP_MAXABS); };
423 424 425 426 427 428

    /**
     * \brief gives the raw current local data with padding included
     * \param[out] size of local data chunk
     * \return pointer to local data
     */
solomon's avatar
solomon committed
429
    dtype * get_raw_data(long_int * size);
430 431 432 433 434 435

    /**
     * \brief gives a read-only copy of the raw current local data with padding included
     * \param[out] size of local data chunk
     * \return pointer to read-only copy of local data
     */
solomon's avatar
solomon committed
436
    const dtype * raw_data(long_int * size) const;
437 438 439 440 441 442 443

    /**
     * \brief gives the global indices and values associated with the local data
     * \param[out] npair number of local values
     * \param[out] global_idx index within global tensor of each data value
     * \param[out] data pointer to local values in the order of the indices
     */
444 445 446
    void read_local(long_int *   npair, 
                    long_int **  global_idx, 
                    dtype **     data) const;
447

448 449 450 451 452
    /**
     * \brief gives the global indices and values associated with the local data
     * \param[out] npair number of local values
     * \param[out] pairs pointer to local key-value pairs
     */
453 454
    void read_local(long_int *         npair,
                    tkv_pair<dtype> ** pairs) const;
455

456 457 458 459 460
    /**
     * \brief collects the entire tensor data on each process (not memory scalable)
     * \param[out] npair number of values in the tensor
     * \param[out] data pointer to the data of the entire tensor
     */
461 462
    void read_all(long_int * npair, 
                  dtype **   data) const;
463 464 465 466 467
    
    /**
     * \brief collects the entire tensor data on each process (not memory scalable)
     * \param[in,out] preallocated data pointer to the data of the entire tensor
     */
468
    long_int read_all(dtype * data) const;
469

470 471 472 473 474 475 476 477
    /**
     * \brief obtains a small number of the biggest elements of the 
     *        tensor in sorted order (e.g. eigenvalues)
     * \param[in] n number of elements to collect
     * \param[in] data output data (should be preallocated to size at least n)
     *
     * WARNING: currently functional only for dtype=double
     */
478
    void get_max_abs(int        n,
479 480
                     dtype *    data);

481 482 483
    /**
     * \brief turns on profiling for tensor
     */
484 485
    void profile_on();
    
486 487 488
    /**
     * \brief turns off profiling for tensor
     */
489 490 491 492 493 494 495
    void profile_off();

    /**
     * \brief sets tensor name
     * \param[in] name new for tensor
     */
    void set_name(char const * name);
496 497 498 499

    /**
     * \brief sets all values in the tensor to val
     */
500
    tCTF_Tensor& operator=(dtype val);
501
    
502 503 504 505 506
    /**
     * \brief sets the tensor
     */
    void operator=(tCTF_Tensor<dtype> A);
    
507 508
    /**
     * \brief associated an index map with the tensor for future operation
509
     * \param[in] idx_map_ index assignment for this tensor
510
     */
511
    tCTF_Idx_Tensor<dtype>& operator[](char const * idx_map_);
512
    
513 514 515 516 517 518
    /**
     * \brief gives handle to sparse index subset of tensors
     * \param[in] indices, vector of indices to sparse tensor
     */
    tCTF_Sparse_Tensor<dtype>& operator[](std::vector<long_int> indices);
    
519 520
    /**
     * \brief prints tensor data to file using process 0
521
     * \param[in] fp file to print to e.g. stdout
522 523 524 525 526 527 528 529 530
     * \param[in] cutoff do not print values of absolute value smaller than this
     */
    void print(FILE * fp = stdout, double cutoff = -1.0) const;

    /**
     * \brief prints two sets of tensor data side-by-side to file using process 0
     * \param[in] fp file to print to e.g. stdout
     * \param[in] A tensor to compare against
     * \param[in] cutoff do not print values of absolute value smaller than this
531
     */
532
    void compare(const tCTF_Tensor<dtype>& A, FILE * fp = stdout, double cutoff = -1.0) const;
533 534

    /**
535
     * \brief frees tCTF tensor
536
     */
537
    ~tCTF_Tensor();
538
};
539

540 541 542 543 544 545 546 547 548 549 550 551 552 553
/**
 * \brief Matrix class which encapsulates a 2D tensor 
 */
template<typename dtype> 
class tCTF_Matrix : public tCTF_Tensor<dtype> {
  public:
    int nrow, ncol, sym;

    /**
     * \brief constructor for a matrix
     * \param[in] nrow number of matrix rows
     * \param[in] ncol number of matrix columns
     * \param[in] sym symmetry of matrix
     * \param[in] world CTF world where the tensor will live
554 555
     * \param[in] name_ an optionary name for the tensor
     * \param[in] profile_ set to 1 to profile contractions involving this tensor
556
     */ 
557 558 559
    tCTF_Matrix(int                 nrow_, 
                int                 ncol_, 
                int                 sym_,
560 561
                tCTF_World<dtype> & world,
                char const *        name_ = NULL,
562
                int                 profile_ = 0);
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577

};

/**
 * \brief Vector class which encapsulates a 1D tensor 
 */
template<typename dtype> 
class tCTF_Vector : public tCTF_Tensor<dtype> {
  public:
    int len;

    /**
     * \brief constructor for a vector
     * \param[in] len_ dimension of vector
     * \param[in] world CTF world where the tensor will live
578 579
     * \param[in] name_ an optionary name for the tensor
     * \param[in] profile_ set to 1 to profile contractions involving this tensor
580
     */ 
581
    tCTF_Vector(int                 len_,
582 583
                tCTF_World<dtype> & world,
                char const *        name_ = NULL,
584
                int                 profile_ = 0);
Edgar Solomonik's avatar
Edgar Solomonik committed
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
};

/**
 * \brief Scalar class which encapsulates a 0D tensor 
 */
template<typename dtype> 
class tCTF_Scalar : public tCTF_Tensor<dtype> {
  public:

    /**
     * \brief constructor for a scalar
     * \param[in] world CTF world where the tensor will live
     */ 
    tCTF_Scalar(tCTF_World<dtype> & world);
    
    /**
     * \brief constructor for a scalar with predefined value
     * \param[in] val scalar value
     * \param[in] world CTF world where the tensor will live
     */ 
605
    tCTF_Scalar(dtype               val,
Edgar Solomonik's avatar
Edgar Solomonik committed
606 607 608 609 610 611 612 613 614 615
                tCTF_World<dtype> & world);

    /**
     * \brief returns scalar value
     */
    dtype get_val();
    
    /**
     * \brief sets scalar value
     */
616
    void set_val(dtype val);
Edgar Solomonik's avatar
Edgar Solomonik committed
617 618 619 620 621

    /**
     * \brief casts into a dtype value
     */
    operator dtype() { return get_val(); }
622 623
};

624 625 626 627 628
template<typename dtype> static
tCTF_Idx_Tensor<dtype>& operator*(double d, tCTF_Idx_Tensor<dtype>& tsr){
  return tsr*d;
}

629 630 631 632
template tCTF_Idx_Tensor<double>& 
            operator*(double d, tCTF_Idx_Tensor<double> & tsr);
template tCTF_Idx_Tensor< std::complex<double> >& 
            operator*(double  d, tCTF_Idx_Tensor< std::complex<double> > & tsr);
633 634 635 636 637 638 639 640 641 642


/**
 * \brief a tensor with an index map associated with it (necessary for overloaded operators)
 */
template<typename dtype>
class tCTF_Idx_Tensor {
  public:
    tCTF_Tensor<dtype> * parent;
    char * idx_map;
643
    int has_contract, has_scale, has_sum, is_intm, is_copy;
644
    double scale;
645
    tCTF_Idx_Tensor<dtype> *NBR;
646 647 648 649 650 651

  public:
    /**
     * \brief constructor takes in a parent tensor and its indices 
     * \param[in] parent_ the parent tensor
     * \param[in] idx_map_ the indices assigned ot this tensor
652
     * \param[in] copy if set to 1, create copy of parent
653
     */
654 655 656 657 658 659 660 661 662 663 664 665
    tCTF_Idx_Tensor(tCTF_Tensor<dtype>* parent_, 
                    const char *        idx_map_,
                    int                 copy = 0);
    
    /**
     * \brief copy constructor
     * \param[in] B tensor to copy
     */
    tCTF_Idx_Tensor(tCTF_Idx_Tensor<dtype>& B,
                    int copy = 0);
    
    tCTF_Idx_Tensor();
666
    
667 668 669 670 671 672 673
    ~tCTF_Idx_Tensor();
    
    /**
     * \brief A = B, compute any operations on operand B and set
     * \param[in] B tensor on the right hand side
     */
    void operator=(tCTF_Idx_Tensor<dtype>& B);
674
    void operator=(dtype B);
675 676 677 678 679 680

    /**
     * \brief A += B, compute any operations on operand B and add
     * \param[in] B tensor on the right hand side
     */
    void operator+=(tCTF_Idx_Tensor<dtype>& B);
681
    void operator+=(dtype B);
682
    
Edgar Solomonik's avatar
Edgar Solomonik committed
683 684 685 686 687
    /**
     * \brief A += B, compute any operations on operand B and add
     * \param[in] B tensor on the right hand side
     */
    void operator-=(tCTF_Idx_Tensor<dtype>& B);
688
    void operator-=(dtype B);
Edgar Solomonik's avatar
Edgar Solomonik committed
689
    
690 691 692 693 694
    /**
     * \brief A -> A*B contract two tensors
     * \param[in] B tensor on the right hand side
     */
    void operator*=(tCTF_Idx_Tensor<dtype>& B);
695
    void operator*=(dtype B);
696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718

    /**
     * \brief C -> A*B contract two tensors
     * \param[in] B tensor on the right hand side
     */
    tCTF_Idx_Tensor<dtype>& operator*(tCTF_Idx_Tensor<dtype>& B);

    /**
     * \brief A -> A+B sums two tensors
     * \param[in] B tensor on the right hand side
     */
    tCTF_Idx_Tensor<dtype>& operator+(tCTF_Idx_Tensor<dtype>& B);
    
    /**
     * \brief A -> A-B subtacts two tensors
     * \param[in] tsr tensor on the right hand side
     */
    tCTF_Idx_Tensor<dtype>& operator-(tCTF_Idx_Tensor<dtype>& B);
    
    /**
     * \brief A -> A-B subtacts two tensors
     * \param[in] tsr tensor on the right hand side
     */
719
    tCTF_Idx_Tensor<dtype>& operator*(double scl);
720 721 722 723 724 725 726


    /**
     * \brief TODO A -> A * B^-1
     * \param[in] B
     */
    //void operator/(tCTF_IdxTensor& tsr);
Edgar Solomonik's avatar
Edgar Solomonik committed
727 728 729 730 731
    
    /**
     * \brief casts into a double if dimension of evaluated expression is 0
     */
    operator dtype();
732 733 734 735

    /**
     * \brief execute ips into output with scale beta
     */    
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
    void run(tCTF_Idx_Tensor<dtype>* output, dtype  beta);

};

/**
 * \brief a sparse subset of a tensor 
 */
template<typename dtype>
class tCTF_Sparse_Tensor {
  public:
    tCTF_Tensor<dtype> * parent;
    std::vector<long_int> indices;
    double scale;

    /** 
      * \brief base constructor 
      */
    tCTF_Sparse_Tensor();
    
    /**
     * \brief initialize a tensor which corresponds to a set of indices 
     * \param[in] indices a vector of global indices to tensor values
     * \param[in] parent dense distributed tensor to which this sparse tensor belongs to
     */
    tCTF_Sparse_Tensor(std::vector<long_int> indices,
                       tCTF_Tensor<dtype> * parent);

    /**
     * \brief initialize a tensor which corresponds to a set of indices 
     * \param[in] number of values this sparse tensor will have locally
     * \param[in] indices an array of global indices to tensor values
     * \param[in] parent dense distributed tensor to which this sparse tensor belongs to
     */
    tCTF_Sparse_Tensor(long_int              n,
                       long_int *            indices,
                       tCTF_Tensor<dtype> * parent);

    /**
     * \brief set the sparse set of indices on the parent tensor to values
     *        forall(j) i = indices[j]; parent[i] = beta*parent[i] + alpha*values[j];
     * \param[in] alpha scaling factor on values array 
     * \param[in] values data, should be of same size as the number of indices (n)
     * \param[in] beta scaling factor to apply to previously existing data
     */
    void write(dtype              alpha, 
               dtype *            values,
               dtype              beta); 

    // C++ overload special-cases of above method
    void operator=(std::vector<dtype> values); 
    void operator+=(std::vector<dtype> values); 
    void operator-=(std::vector<dtype> values); 
    void operator=(dtype * values); 
    void operator+=(dtype * values); 
    void operator-=(dtype * values); 

    /**
     * \brief read the sparse set of indices on the parent tensor to values
     *        forall(j) i = indices[j]; values[j] = alpha*parent[i] + beta*values[j];
     * \param[in] alpha scaling factor on parent array 
     * \param[in] values data, should be preallocated to the same size as the number of indices (n)
     * \param[in] beta scaling factor to apply to previously existing data in values
     */
    void read(dtype              alpha, 
              dtype *            values,
              dtype              beta); 
802

803 804 805
    // C++ overload special-cases of above method
    operator std::vector<dtype>();
    operator dtype*();
806 807
};

solomon's avatar
solomon committed
808 809 810
/**
 * \brief local process walltime measurement
 */
811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826
class CTF_Timer{
  public:
    char const * timer_name;
    int index;
    int exited;
    int original;
  
  public:
    CTF_Timer(char const * name);
    ~CTF_Timer();
    void stop();
    void start();
    void exit();
    
};

solomon's avatar
solomon committed
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
/**
 * \brief measures flops done in a code region
 */
class CTF_Flop_Counter{
  public:
    long_int start_count;

  public:
    /**
     * \brief constructor, starts counter
     */
    CTF_Flop_Counter();
    ~CTF_Flop_Counter();

    /**
     * \brief restarts counter
     */
    void zero();

    /**
     * \brief get total flop count over all counters in comm
     */
    long_int count(MPI_Comm comm = MPI_COMM_SELF);

};

853

854 855
/* these typedefs yield a non-tempalated interface for double and complex<double> */
typedef tCTF<double>                        CTF;
856
typedef tCTF_Idx_Tensor<double>             CTF_Idx_Tensor;
857
typedef tCTF_Tensor<double>                 CTF_Tensor;
858
typedef tCTF_Sparse_Tensor<double>          CTF_Sparse_Tensor;
859 860 861 862 863 864 865 866
typedef tCTF_Matrix<double>                 CTF_Matrix;
typedef tCTF_Vector<double>                 CTF_Vector;
typedef tCTF_Scalar<double>                 CTF_Scalar;
typedef tCTF_World<double>                  CTF_World;
typedef tCTF_fscl<double>                   CTF_fscl;
typedef tCTF_fsum<double>                   CTF_fsum;
typedef tCTF_fctr<double>                   CTF_fctr;
typedef tCTF< std::complex<double> >        cCTF;
867
typedef tCTF_Idx_Tensor< std::complex<double> > cCTF_Idx_Tensor;
Edgar Solomonik's avatar
Edgar Solomonik committed
868
typedef tCTF_Tensor< std::complex<double> > cCTF_Tensor;
869
typedef tCTF_Sparse_Tensor< std::complex<double> > cCTF_Sparse_Tensor;
Edgar Solomonik's avatar
Edgar Solomonik committed
870 871
typedef tCTF_Matrix< std::complex<double> > cCTF_Matrix;
typedef tCTF_Vector< std::complex<double> > cCTF_Vector;
Edgar Solomonik's avatar
Edgar Solomonik committed
872
typedef tCTF_Scalar< std::complex<double> > cCTF_Scalar;
873 874 875 876
typedef tCTF_World< std::complex<double> >  cCTF_World;
typedef tCTF_fscl< std::complex<double> >   cCTF_fscl;
typedef tCTF_fsum< std::complex<double> >   cCTF_fsum;
typedef tCTF_fctr< std::complex<double> >   cCTF_fctr;
877
#endif