<commit_before>/*
Copyright 2016 Sebastien Riou
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include "stdio.h"
#include "time.h"
#include <random>

#include <string.h>
#define TEST_FAIL 0
#define TEST_PASS 1

#include <stdio.h>
#include <stdint.h>

static void print_bytes_sep(const char *msg,const unsigned char *buf, unsigned int size, const char m2[], const char sep[]){
	unsigned int i;
	printf("%s",msg);
	for(i=0;i<size-1;i++) printf("%02X%s",buf[i],sep);
	if(i<size) printf("%02X",buf[i]);
	printf("%s", m2);
}
static void print_bytes(const char m[],const uint8_t *buf, unsigned int size, const char m2[]){print_bytes_sep(m,buf,size,m2," ");}
static void println_bytes(const char m[],const uint8_t *buf, unsigned int size){print_bytes(m,buf,size,"\n");}
static void print_128(const char m[], const uint8_t a[16], const char m2[]){
	print_bytes_sep( m,a   ,4,"_","");
	print_bytes_sep("",a+4 ,4,"_","");
	print_bytes_sep("",a+8 ,4,"_","");
	print_bytes_sep("",a+12,4,m2 ,"");
}
static void print_64 (const char m[], const uint8_t a[ 8], const char m2[]){
	print_bytes_sep( m,a   ,4,"_","");
	print_bytes_sep("",a+4 ,4,m2 ,"");
}
static void println_128(const char m[], const uint8_t a[16]){print_128(m,a,"\n");}
static void println_64 (const char m[], const uint8_t a[ 8]){print_64 (m,a,"\n");}

int hexdigit_value(char c){
	int nibble = -1;
	if(('0'<=c) && (c<='9')) nibble = c-'0';
	if(('a'<=c) && (c<='f')) nibble = c-'a' + 10;
	if(('A'<=c) && (c<='F')) nibble = c-'A' + 10;
	return nibble;
}

int is_hex_digit(char c){
	return -1!=hexdigit_value(c);
}

void hexstr_to_bytes(unsigned int size_in_bytes, void *dst, const char * const hexstr){
	unsigned int char_index = 0;
	unsigned int hexdigit_cnt=0;
	uint8_t* dst_bytes = (uint8_t*)dst;
	memset(dst,0,size_in_bytes);
	while(hexdigit_cnt<size_in_bytes*2){
		char c = hexstr[char_index++];
		if(0==c) {
			printf("\nERROR: could not find %d hex digits in string '%s'.\n",size_in_bytes*2,hexstr);
			printf("char_index=%d, hexdigit_cnt=%d\n",char_index,hexdigit_cnt);
			exit(-1);
		}
		if(is_hex_digit(c)) {
			unsigned int shift = 4 - 4*(hexdigit_cnt & 1);
			uint8_t nibble = hexdigit_value(c);
			dst_bytes[hexdigit_cnt/2] |= nibble << shift;
			hexdigit_cnt++;
		}
	}
}

void bytes_to_hexstr(char *dst,uint8_t *bytes, unsigned int nBytes){
	unsigned int i;
	for(i=0;i<nBytes;i++){
		sprintf(dst+2*i,"%02X",bytes[i]);
	}
}

void assert_equal_bytes(const uint8_t *const a, const uint8_t *const b, unsigned int size_in_bytes){
	for(unsigned int i=0;i<size_in_bytes;i++){
		if(a[i]!=b[i]){
			printf("\nERROR: assertion failed.\n");
			print_bytes_sep("a=",a,size_in_bytes,"\n"," ");
			print_bytes_sep("b=",b,size_in_bytes,"\n"," ");
			printf("a[%u]=0x%02X\nb[%u]=0x%02X\n",i,a[i],i,b[i]);
			exit(-2);
		}
	}
}

typedef struct testvector_struct {
  uint8_t plain [8];
  uint8_t k0    [8];
  uint8_t k1    [8];
  uint8_t cipher[8];
} testvector_t;

static const char * testvectors[] = {
	//test vectors from original Prince paper (http://eprint.iacr.org/2012/529.pdf)
	"     plain              k0               k1             cipher     ",
	"0000000000000000 0000000000000000 0000000000000000 818665aa0d02dfda",
	"ffffffffffffffff 0000000000000000 0000000000000000 604ae6ca03c20ada",
	"0000000000000000 ffffffffffffffff 0000000000000000 9fb51935fc3df524",
	"0000000000000000 0000000000000000 ffffffffffffffff 78a54cbe737bb7ef",
	"0123456789abcdef 0000000000000000 fedcba9876543210 ae25ad3ca8fa9ccf",
	//custom test vectors from here, cipher values generated with prince_ref.h !
	"0123456789ABCDEF 0011223344556677 8899AABBCCDDEEFF D6DCB5978DE756EE",
	"0123456789ABCDEF 0112233445566778 899AABBCCDDEEFF0 392F599F46761CD3",
	"F0123456789ABCDE 0112233445566778 899AABBCCDDEEFF0 4FB5E332B9B409BB",
	"69C4E0D86A7B0430 D8CDB78070B4C55A 818665AA0D02DFDA 43C6B256D79DE7E8"
};

#define STR_EXPAND(tok) #tok
#define STR(tok) STR_EXPAND(tok)
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
//#define PRINCE_PRINT(a) printf("\t%016" PRIx64 " %s\n",a,STR(a));
#define PRINCE_PRINT(a) do{\
		uint8_t raw_bytes[8];\
		uint64_to_bytes(a,raw_bytes);\
		print_64("\t",raw_bytes," " STR(a) "\n");\
	}while(0)
#include "prince_ref.h"
int basic_test(void){
	for(int i=1;i<sizeof(testvectors)/sizeof(char*);i++){
		testvector_t tv;
		hexstr_to_bytes(sizeof(tv), &tv, testvectors[i]);
		printf("test vector %d\n",i);
		print_64  ( "plain:",tv.plain ," ");
		print_64  (    "k0:",tv.k0    ," ");
		print_64  (    "k1:",tv.k1    ," ");
		println_64("cipher:",tv.cipher);
		printf("encryption:\n");
		uint8_t result[8];
		uint8_t key[16];
		memcpy(key  ,tv.k0,8);
		memcpy(key+8,tv.k1,8);
		println_128("key:",key);
		prince_encrypt(tv.plain,key,result);
		assert_equal_bytes(tv.cipher,result,8);
		printf("decryption:\n");
		prince_decrypt(tv.cipher,key,result);
		assert_equal_bytes(tv.plain,result,8);
	}
	return TEST_PASS;
}

int main(void){
	if(TEST_PASS==basic_test()){
		printf("Basic Test PASS\n");
	} else {
		printf("Basic Test FAIL\n");
	}
	return 0;
}
<commit_msg>check to see if the self test fail is detected by TravisCI<commit_after>/*
Copyright 2016 Sebastien Riou
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include "stdio.h"
#include "time.h"
#include <random>

#include <string.h>
#define TEST_FAIL 0
#define TEST_PASS 1

#include <stdio.h>
#include <stdint.h>

static void print_bytes_sep(const char *msg,const unsigned char *buf, unsigned int size, const char m2[], const char sep[]){
	unsigned int i;
	printf("%s",msg);
	for(i=0;i<size-1;i++) printf("%02X%s",buf[i],sep);
	if(i<size) printf("%02X",buf[i]);
	printf("%s", m2);
}
static void print_bytes(const char m[],const uint8_t *buf, unsigned int size, const char m2[]){print_bytes_sep(m,buf,size,m2," ");}
static void println_bytes(const char m[],const uint8_t *buf, unsigned int size){print_bytes(m,buf,size,"\n");}
static void print_128(const char m[], const uint8_t a[16], const char m2[]){
	print_bytes_sep( m,a   ,4,"_","");
	print_bytes_sep("",a+4 ,4,"_","");
	print_bytes_sep("",a+8 ,4,"_","");
	print_bytes_sep("",a+12,4,m2 ,"");
}
static void print_64 (const char m[], const uint8_t a[ 8], const char m2[]){
	print_bytes_sep( m,a   ,4,"_","");
	print_bytes_sep("",a+4 ,4,m2 ,"");
}
static void println_128(const char m[], const uint8_t a[16]){print_128(m,a,"\n");}
static void println_64 (const char m[], const uint8_t a[ 8]){print_64 (m,a,"\n");}

int hexdigit_value(char c){
	int nibble = -1;
	if(('0'<=c) && (c<='9')) nibble = c-'0';
	if(('a'<=c) && (c<='f')) nibble = c-'a' + 10;
	if(('A'<=c) && (c<='F')) nibble = c-'A' + 10;
	return nibble;
}

int is_hex_digit(char c){
	return -1!=hexdigit_value(c);
}

void hexstr_to_bytes(unsigned int size_in_bytes, void *dst, const char * const hexstr){
	unsigned int char_index = 0;
	unsigned int hexdigit_cnt=0;
	uint8_t* dst_bytes = (uint8_t*)dst;
	memset(dst,0,size_in_bytes);
	while(hexdigit_cnt<size_in_bytes*2){
		char c = hexstr[char_index++];
		if(0==c) {
			printf("\nERROR: could not find %d hex digits in string '%s'.\n",size_in_bytes*2,hexstr);
			printf("char_index=%d, hexdigit_cnt=%d\n",char_index,hexdigit_cnt);
			exit(-1);
		}
		if(is_hex_digit(c)) {
			unsigned int shift = 4 - 4*(hexdigit_cnt & 1);
			uint8_t nibble = hexdigit_value(c);
			dst_bytes[hexdigit_cnt/2] |= nibble << shift;
			hexdigit_cnt++;
		}
	}
}

void bytes_to_hexstr(char *dst,uint8_t *bytes, unsigned int nBytes){
	unsigned int i;
	for(i=0;i<nBytes;i++){
		sprintf(dst+2*i,"%02X",bytes[i]);
	}
}

void assert_equal_bytes(const uint8_t *const a, const uint8_t *const b, unsigned int size_in_bytes){
	for(unsigned int i=0;i<size_in_bytes;i++){
		if(a[i]!=b[i]){
			printf("\nERROR: assertion failed.\n");
			print_bytes_sep("a=",a,size_in_bytes,"\n"," ");
			print_bytes_sep("b=",b,size_in_bytes,"\n"," ");
			printf("a[%u]=0x%02X\nb[%u]=0x%02X\n",i,a[i],i,b[i]);
			exit(-2);
		}
	}
}

typedef struct testvector_struct {
  uint8_t plain [8];
  uint8_t k0    [8];
  uint8_t k1    [8];
  uint8_t cipher[8];
} testvector_t;

static const char * testvectors[] = {
	//test vectors from original Prince paper (http://eprint.iacr.org/2012/529.pdf)
	"     plain              k0               k1             cipher     ",
	"0000000000000000 0000000000000000 0000000000000000 818665aa0d02dfda",
	"ffffffffffffffff 0000000000000000 0000000000000000 604ae6ca03c20ada",
	"0000000000000000 ffffffffffffffff 0000000000000000 9fb51935fc3df524",
	"0000000000000000 0000000000000000 ffffffffffffffff 78a54cbe737bb7ef",
	"0123456789abcdef 0000000000000000 fedcba9876543210 ae25ad3ca8fa9ccf",
	//custom test vectors from here, cipher values generated with prince_ref.h !
	"0123456789ABCDEF 0011223344556677 8899AABBCCDDEEFF D6DCB5978DE756EE",
	"0123456789ABCDEF 0112233445566778 899AABBCCDDEEFF0 392F599F46761CD3",
	"F0123456789ABCDE 0112233445566778 899AABBCCDDEEFF0 4FB5E332B9B409BB",
	"69C4E0D86A7B0430 D8CDB78070B4C55A 818665AA0D02DFDA 43C6B256D79DE7E8"
};

#define STR_EXPAND(tok) #tok
#define STR(tok) STR_EXPAND(tok)
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
//#define PRINCE_PRINT(a) printf("\t%016" PRIx64 " %s\n",a,STR(a));
#define PRINCE_PRINT(a) do{\
		uint8_t raw_bytes[8];\
		uint64_to_bytes(a,raw_bytes);\
		print_64("\t",raw_bytes," " STR(a) "\n");\
	}while(0)
#include "prince_ref.h"
int basic_test(void){
	for(int i=1;i<sizeof(testvectors)/sizeof(char*);i++){
		testvector_t tv;
		hexstr_to_bytes(sizeof(tv), &tv, testvectors[i]);
		printf("test vector %d\n",i);
		print_64  ( "plain:",tv.plain ," ");
		print_64  (    "k0:",tv.k0    ," ");
		print_64  (    "k1:",tv.k1    ," ");
		println_64("cipher:",tv.cipher);
		printf("encryption:\n");
		uint8_t result[8];
		uint8_t key[16];
		memcpy(key  ,tv.k0,8);
		memcpy(key+8,tv.k1,8);
		println_128("key:",key);
		prince_encrypt(tv.plain,key,result);
		assert_equal_bytes(tv.cipher,result,8);
		printf("decryption:\n");
		prince_decrypt(tv.cipher,key,result);
		assert_equal_bytes(tv.plain,result,8);
	}
	return TEST_PASS;
}

int main(void){
	if(TEST_PASS==basic_test()){
		printf("Basic Test PASS\n");
	} else {
		printf("Basic Test FAIL\n");
        return -1;
	}
	return -1;
}
<|endoftext|>


<commit_before>/*Copyright (c) 2011, Edgar Solomonik, all rights reserved.*/

/** \addtogroup examples
  * @{
  * \defgroup CCSD
  * @{
  * \brief A Coupled Cluster Singles and Doubles contraction code extracted from Aquarius
  */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <math.h>
#include <assert.h>
#include <algorithm>
#include <ctf.hpp>
#include "../src/shared/util.h"

void divide(double const alpha, double const a, double const b, double & c){
  if (fabs(b) > 0.0);
    c+=alpha*(a/b);
}

class Integrals {
  public:
  CTF_World * dw;
  CTF_Tensor aa;
  CTF_Tensor ii;
  CTF_Tensor ab;
  CTF_Tensor ai;
  CTF_Tensor ia;
  CTF_Tensor ij;
  CTF_Tensor abcd;
  CTF_Tensor abci;
  CTF_Tensor aibc;
  CTF_Tensor aibj;
  CTF_Tensor abij;
  CTF_Tensor ijab;
  CTF_Tensor aijk;
  CTF_Tensor ijak;
  CTF_Tensor ijkl;

  Integrals(int no, int nv, CTF_World &dw_){
    int shapeASAS[] = {AS,NS,AS,NS};
    int shapeASNS[] = {AS,NS,NS,NS};
    int shapeNSNS[] = {NS,NS,NS,NS};
    int shapeNSAS[] = {NS,NS,AS,NS};
    int vvvv[]      = {nv,nv,nv,nv};
    int vvvo[]      = {nv,nv,nv,no};
    int vovv[]      = {nv,no,nv,nv};
    int vovo[]      = {nv,no,nv,no};
    int vvoo[]      = {nv,nv,no,no};
    int oovv[]      = {no,no,nv,nv};
    int vooo[]      = {nv,no,no,no};
    int oovo[]      = {no,no,nv,no};
    int oooo[]      = {no,no,no,no};

    dw = &dw_;

    aa = CTF_Vector(nv,dw_);
    ii = CTF_Vector(no,dw_);

    ab = CTF_Matrix(nv,nv,AS,dw_,"Vab",1);
    ai = CTF_Matrix(nv,no,NS,dw_,"Vai",1);
    ia = CTF_Matrix(no,nv,NS,dw_,"Via",1);
    ij = CTF_Matrix(no,no,AS,dw_,"Vij",1);

    abcd = CTF_Tensor(4,vvvv,shapeASAS,dw_,"Vabcd",1);
    abci = CTF_Tensor(4,vvvo,shapeASNS,dw_,"Vabci",1);
    aibc = CTF_Tensor(4,vovv,shapeNSAS,dw_,"Vaibc",1);
    aibj = CTF_Tensor(4,vovo,shapeNSNS,dw_,"Vaibj",1);
    abij = CTF_Tensor(4,vvoo,shapeASAS,dw_,"Vabij",1);
    ijab = CTF_Tensor(4,oovv,shapeASAS,dw_,"Vijab",1);
    aijk = CTF_Tensor(4,vooo,shapeNSAS,dw_,"Vaijk",1);
    ijak = CTF_Tensor(4,oovo,shapeASNS,dw_,"Vijak",1);
    ijkl = CTF_Tensor(4,oooo,shapeASAS,dw_,"Vijkl",1);
  }

  void fill_rand(){
    int i, rank;
    long_int j, sz, * indices;
    double * values;

    CTF_Tensor * tarr[] =  {&aa, &ii, &ab, &ai, &ia, &ij,
                            &abcd, &abci, &aibc, &aibj,
                            &abij, &ijab, &aijk, &ijak, &ijkl};
    MPI_Comm comm = dw->comm;
    MPI_Comm_rank(comm, &rank);

    srand48(rank*13);

    for (i=0; i<15; i++){
      tarr[i]->read_local(&sz, &indices, &values);
//      for (j=0; j<sz; j++) values[j] = drand48()-.5;
      for (j=0; j<sz; j++) values[j] = ((indices[j]*16+i)%13077)/13077. -.5;
      tarr[i]->write(sz, indices, values);
      free(indices), free(values);
    }
  }

  tCTF_Idx_Tensor<double> operator[](char const * idx_map_){
    int i, lenm, no, nv;
    lenm = strlen(idx_map_);
    char new_idx_map[lenm+1];
    new_idx_map[lenm]='\0';
    no = 0;
    nv = 0;
    for (i=0; i<lenm; i++){
      if (idx_map_[i] >= 'a' && idx_map_[i] <= 'h'){
        new_idx_map[i] = 'a'+nv;
        nv++;
      } else if (idx_map_[i] >= 'i' && idx_map_[i] <= 'n'){
        new_idx_map[i] = 'i'+no;
        no++;
      }
    }
//    printf("indices %s are %s\n",idx_map_,new_idx_map);
    if (0 == strcmp("a",new_idx_map)) return aa[idx_map_];
    if (0 == strcmp("i",new_idx_map)) return ii[idx_map_];
    if (0 == strcmp("ab",new_idx_map)) return ab[idx_map_];
    if (0 == strcmp("ai",new_idx_map)) return ai[idx_map_];
    if (0 == strcmp("ia",new_idx_map)) return ia[idx_map_];
    if (0 == strcmp("ij",new_idx_map)) return ij[idx_map_];
    if (0 == strcmp("abcd",new_idx_map)) return abcd[idx_map_];
    if (0 == strcmp("abci",new_idx_map)) return abci[idx_map_];
    if (0 == strcmp("aibc",new_idx_map)) return aibc[idx_map_];
    if (0 == strcmp("aibj",new_idx_map)) return aibj[idx_map_];
    if (0 == strcmp("abij",new_idx_map)) return abij[idx_map_];
    if (0 == strcmp("ijab",new_idx_map)) return ijab[idx_map_];
    if (0 == strcmp("aijk",new_idx_map)) return aijk[idx_map_];
    if (0 == strcmp("ijak",new_idx_map)) return ijak[idx_map_];
    if (0 == strcmp("ijkl",new_idx_map)) return ijkl[idx_map_];
    printf("Invalid integral indices\n");
    ABORT;
//shut up compiler
    return aa[idx_map_];
  }
};

class Amplitudes {
  public:
  CTF_Tensor ai;
  CTF_Tensor abij;
  CTF_World * dw;

  Amplitudes(int no, int nv, CTF_World &dw_){
    dw = &dw_;
    int shapeASAS[] = {AS,NS,AS,NS};
    int vvoo[]      = {nv,nv,no,no};

    ai = CTF_Matrix(nv,no,NS,dw_,"Tai",1);

    abij = CTF_Tensor(4,vvoo,shapeASAS,dw_,"Tabij",1);
  }

  tCTF_Idx_Tensor<double> operator[](char const * idx_map_){
    if (strlen(idx_map_) == 4) return abij[idx_map_];
    else return ai[idx_map_];
  }
};

void ccsd(Integrals   &V,
          Amplitudes  &T){
  tCTF_Schedule<double> sched;
  //sched.record();

  CTF_Tensor T21 = CTF_Tensor(T.abij);
  T21["abij"] += .5*T["ai"]*T["bj"];

  CTF_Idx_Tensor Fme(V["me"]);
  Fme += V["me"];
  Fme += V["mnef"]*T["fn"];

  CTF_Idx_Tensor Fae(V["ae"]);
  Fae += V["ae"];
  Fae -= Fme*T["am"];
  Fae -=.5*V["mnef"]*T["afmn"];
  Fae += V["anef"]*T["fn"];

  CTF_Idx_Tensor Fmi(V["mi"]);
  Fmi += V["mi"];
  Fmi += Fme*T["ei"];
  Fmi += .5*V["mnef"]*T["efin"];
  Fmi += V["mnfi"]*T["fn"];

  CTF_Idx_Tensor Wmnei(V["mnei"]);
  Wmnei += V["mnei"];
  Wmnei += V["mnef"]*T["fi"];

  CTF_Idx_Tensor Wmnij(V["mnij"]);
  Wmnij += V["mnij"];
  Wmnij -= V["mnei"]*T["ej"];
  Wmnij += V["mnef"]*T21["efij"];

  CTF_Idx_Tensor Wamei(V["amei"]);
  Wamei += V["amei"];
  Wamei -= Wmnei*T["an"];
  Wamei += V["amef"]*T["fi"];
  Wamei += .5*V["mnef"]*T["afin"];

  CTF_Idx_Tensor Wamij(V["amij"]);
  Wamij += V["amij"];
  Wamij += V["amei"]*T["ej"];
  Wamij += V["amef"]*T["efij"];

  CTF_Idx_Tensor Zai(V["ai"]);
  Zai += V["ai"];
  Zai -= Fmi*T["am"];
  Zai += V["ae"]*T["ei"];
  Zai += V["amei"]*T["em"];
  Zai += V["aeim"]*Fme;
  Zai += .5*V["amef"]*T21["efim"];
  Zai -= .5*Wmnei*T21["eamn"];

  CTF_Idx_Tensor Zabij(V["abij"]);
  Zabij += V["abij"];
  Zabij += V["abei"]*T["ej"];
  Zabij += Wamei*T["ebmj"];
  Zabij -= Wamij*T["bm"];
  Zabij += Fae*T["ebij"];
  Zabij -= Fmi*T["abmj"];
  Zabij += .5*V["abef"]*T21["efij"];
  Zabij += .5*Wmnij*T21["abmn"];

  CTF_fctr fctr;
  fctr.func_ptr = ÷

  CTF_Tensor Dai(2, V.ai.len, V.ai.sym, *V.dw);
  int sh_sym[4] = {SH, NS, SH, NS};
  CTF_Tensor Dabij(4, V.abij.len, sh_sym, *V.dw);
  Dai["ai"] += V["i"];
  Dai["ai"] -= V["a"];

  Dabij["abij"] += V["i"];
  Dabij["abij"] += V["j"];
  Dabij["abij"] -= V["a"];
  Dabij["abij"] -= V["b"];

  sched.execute();

  T.ai.contract(1.0, *(Zai.parent), "ai", Dai, "ai", 0.0, "ai", fctr);
  T.abij.contract(1.0, *(Zabij.parent), "abij", Dabij, "abij", 0.0, "abij", fctr);
}

#ifndef TEST_SUITE

char* getCmdOption(char ** begin,
                   char ** end,
                   const   std::string & option){
  char ** itr = std::find(begin, end, option);
  if (itr != end && ++itr != end){
    return *itr;
  }
  return 0;
}

int main(int argc, char ** argv){
  int rank, np, niter, no, nv, i;
  int const in_num = argc;
  char ** input_str = argv;

  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &np);

  if (getCmdOption(input_str, input_str+in_num, "-no")){
    no = atoi(getCmdOption(input_str, input_str+in_num, "-no"));
    if (no < 0) no= 4;
  } else no = 4;
  if (getCmdOption(input_str, input_str+in_num, "-nv")){
    nv = atoi(getCmdOption(input_str, input_str+in_num, "-nv"));
    if (nv < 0) nv = 6;
  } else nv = 6;
  if (getCmdOption(input_str, input_str+in_num, "-niter")){
    niter = atoi(getCmdOption(input_str, input_str+in_num, "-niter"));
    if (niter < 0) niter = 1;
  } else niter = 1;

  {
    CTF_World dw(argc, argv);
    {
      Integrals V(no, nv, dw);
      V.fill_rand();
      Amplitudes T(no, nv, dw);
      for (i=0; i<niter; i++){
        double d = MPI_Wtime();
        ccsd(V,T);
        if (rank == 0)
          printf("Completed %dth CCSD iteration in time = %lf, |T| is %lf\n",
                  i, MPI_Wtime()-d, T.ai.norm2()+T.abij.norm2());
        else {
          T.ai.norm2();
          T.abij.norm2();
        }
        T["ai"] = (1./T.ai.norm2())*T["ai"];
        T["abij"] = (1./T.abij.norm2())*T["abij"];
      }
    }
  }

  MPI_Finalize();
  return 0;
}
/**
 * @}
 * @}
 */

#endif

<commit_msg>xMerge branch 'master' into scheduler<commit_after>/*Copyright (c) 2011, Edgar Solomonik, all rights reserved.*/

/** \addtogroup examples
  * @{
  * \defgroup CCSD
  * @{
  * \brief A Coupled Cluster Singles and Doubles contraction code extracted from Aquarius
  */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <math.h>
#include <assert.h>
#include <algorithm>
#include <ctf.hpp>
#include "../src/shared/util.h"

void divide(double const alpha, double const a, double const b, double & c){
  if (fabs(b) > 0.0);
    c+=alpha*(a/b);
}

class Integrals {
  public:
  CTF_World * dw;
  CTF_Tensor aa;
  CTF_Tensor ii;
  CTF_Tensor ab;
  CTF_Tensor ai;
  CTF_Tensor ia;
  CTF_Tensor ij;
  CTF_Tensor abcd;
  CTF_Tensor abci;
  CTF_Tensor aibc;
  CTF_Tensor aibj;
  CTF_Tensor abij;
  CTF_Tensor ijab;
  CTF_Tensor aijk;
  CTF_Tensor ijak;
  CTF_Tensor ijkl;

  Integrals(int no, int nv, CTF_World &dw_){
    int shapeASAS[] = {AS,NS,AS,NS};
    int shapeASNS[] = {AS,NS,NS,NS};
    int shapeNSNS[] = {NS,NS,NS,NS};
    int shapeNSAS[] = {NS,NS,AS,NS};
    int vvvv[]      = {nv,nv,nv,nv};
    int vvvo[]      = {nv,nv,nv,no};
    int vovv[]      = {nv,no,nv,nv};
    int vovo[]      = {nv,no,nv,no};
    int vvoo[]      = {nv,nv,no,no};
    int oovv[]      = {no,no,nv,nv};
    int vooo[]      = {nv,no,no,no};
    int oovo[]      = {no,no,nv,no};
    int oooo[]      = {no,no,no,no};

    dw = &dw_;

    aa = CTF_Vector(nv,dw_);
    ii = CTF_Vector(no,dw_);

    ab = CTF_Matrix(nv,nv,AS,dw_,"Vab",1);
    ai = CTF_Matrix(nv,no,NS,dw_,"Vai",1);
    ia = CTF_Matrix(no,nv,NS,dw_,"Via",1);
    ij = CTF_Matrix(no,no,AS,dw_,"Vij",1);

    abcd = CTF_Tensor(4,vvvv,shapeASAS,dw_,"Vabcd",1);
    abci = CTF_Tensor(4,vvvo,shapeASNS,dw_,"Vabci",1);
    aibc = CTF_Tensor(4,vovv,shapeNSAS,dw_,"Vaibc",1);
    aibj = CTF_Tensor(4,vovo,shapeNSNS,dw_,"Vaibj",1);
    abij = CTF_Tensor(4,vvoo,shapeASAS,dw_,"Vabij",1);
    ijab = CTF_Tensor(4,oovv,shapeASAS,dw_,"Vijab",1);
    aijk = CTF_Tensor(4,vooo,shapeNSAS,dw_,"Vaijk",1);
    ijak = CTF_Tensor(4,oovo,shapeASNS,dw_,"Vijak",1);
    ijkl = CTF_Tensor(4,oooo,shapeASAS,dw_,"Vijkl",1);
  }

  void fill_rand(){
    int i, rank;
    long_int j, sz, * indices;
    double * values;

    CTF_Tensor * tarr[] =  {&aa, &ii, &ab, &ai, &ia, &ij,
                            &abcd, &abci, &aibc, &aibj,
                            &abij, &ijab, &aijk, &ijak, &ijkl};
    MPI_Comm comm = dw->comm;
    MPI_Comm_rank(comm, &rank);

    srand48(rank*13);

    for (i=0; i<15; i++){
      tarr[i]->read_local(&sz, &indices, &values);
//      for (j=0; j<sz; j++) values[j] = drand48()-.5;
      for (j=0; j<sz; j++) values[j] = ((indices[j]*16+i)%13077)/13077. -.5;
      tarr[i]->write(sz, indices, values);
      free(indices), free(values);
    }
  }

  tCTF_Idx_Tensor<double> operator[](char const * idx_map_){
    int i, lenm, no, nv;
    lenm = strlen(idx_map_);
    char new_idx_map[lenm+1];
    new_idx_map[lenm]='\0';
    no = 0;
    nv = 0;
    for (i=0; i<lenm; i++){
      if (idx_map_[i] >= 'a' && idx_map_[i] <= 'h'){
        new_idx_map[i] = 'a'+nv;
        nv++;
      } else if (idx_map_[i] >= 'i' && idx_map_[i] <= 'n'){
        new_idx_map[i] = 'i'+no;
        no++;
      }
    }
//    printf("indices %s are %s\n",idx_map_,new_idx_map);
    if (0 == strcmp("a",new_idx_map)) return aa[idx_map_];
    if (0 == strcmp("i",new_idx_map)) return ii[idx_map_];
    if (0 == strcmp("ab",new_idx_map)) return ab[idx_map_];
    if (0 == strcmp("ai",new_idx_map)) return ai[idx_map_];
    if (0 == strcmp("ia",new_idx_map)) return ia[idx_map_];
    if (0 == strcmp("ij",new_idx_map)) return ij[idx_map_];
    if (0 == strcmp("abcd",new_idx_map)) return abcd[idx_map_];
    if (0 == strcmp("abci",new_idx_map)) return abci[idx_map_];
    if (0 == strcmp("aibc",new_idx_map)) return aibc[idx_map_];
    if (0 == strcmp("aibj",new_idx_map)) return aibj[idx_map_];
    if (0 == strcmp("abij",new_idx_map)) return abij[idx_map_];
    if (0 == strcmp("ijab",new_idx_map)) return ijab[idx_map_];
    if (0 == strcmp("aijk",new_idx_map)) return aijk[idx_map_];
    if (0 == strcmp("ijak",new_idx_map)) return ijak[idx_map_];
    if (0 == strcmp("ijkl",new_idx_map)) return ijkl[idx_map_];
    printf("Invalid integral indices\n");
    ABORT;
//shut up compiler
    return aa[idx_map_];
  }
};

class Amplitudes {
  public:
  CTF_Tensor ai;
  CTF_Tensor abij;
  CTF_World * dw;

  Amplitudes(int no, int nv, CTF_World &dw_){
    dw = &dw_;
    int shapeASAS[] = {AS,NS,AS,NS};
    int vvoo[]      = {nv,nv,no,no};

    ai = CTF_Matrix(nv,no,NS,dw_,"Tai",1);

    abij = CTF_Tensor(4,vvoo,shapeASAS,dw_,"Tabij",1);
  }

  tCTF_Idx_Tensor<double> operator[](char const * idx_map_){
    if (strlen(idx_map_) == 4) return abij[idx_map_];
    else return ai[idx_map_];
  }

  void fill_rand(){
    int i, rank;
    long_int j, sz, * indices;
    double * values;

    CTF_Tensor * tarr[] =  {&ai, &abij};
    MPI_Comm comm = dw->comm;
    MPI_Comm_rank(comm, &rank);

    srand48(rank*25);

    for (i=0; i<2; i++){
      tarr[i]->read_local(&sz, &indices, &values);
//      for (j=0; j<sz; j++) values[j] = drand48()-.5;
      for (j=0; j<sz; j++) values[j] = ((indices[j]*13+i)%13077)/13077. -.5;
      tarr[i]->write(sz, indices, values);
      free(indices), free(values);
    }
  }
};

void ccsd(Integrals   &V,
          Amplitudes  &T){

  CTF_Tensor T21 = CTF_Tensor(T.abij);
  T21["abij"] += .5*T["ai"]*T["bj"];

  CTF_Tensor tFme(*V["me"].parent);
  CTF_Idx_Tensor Fme(&tFme,"me");
  Fme += V["me"];
  Fme += V["mnef"]*T["fn"];

  CTF_Tensor tFae(*V["ae"].parent);
  CTF_Idx_Tensor Fae(&tFae,"ae");
  Fae += V["ae"];
  Fae -= Fme*T["am"];
  Fae -=.5*V["mnef"]*T["afmn"];
  Fae += V["anef"]*T["fn"];

  CTF_Tensor tFmi(*V["mi"].parent);
  CTF_Idx_Tensor Fmi(&tFmi,"mi");
  Fmi += V["mi"];
  Fmi += Fme*T["ei"];
  Fmi += .5*V["mnef"]*T["efin"];
  Fmi += V["mnfi"]*T["fn"];

  CTF_Tensor tWmnei(*V["mnei"].parent);
  CTF_Idx_Tensor Wmnei(&tWmnei,"mnei");
  Wmnei += V["mnei"];
  Wmnei += V["mnei"];
  Wmnei += V["mnef"]*T["fi"];

  CTF_Tensor tWmnij(*V["mnij"].parent);
  CTF_Idx_Tensor Wmnij(&tWmnij,"mnij");
  Wmnij += V["mnij"];
  Wmnij -= V["mnei"]*T["ej"];
  Wmnij += V["mnef"]*T21["efij"];

  CTF_Tensor tWamei(*V["amei"].parent);
  CTF_Idx_Tensor Wamei(&tWamei,"amei");
  Wamei += V["amei"];
  Wamei -= Wmnei*T["an"];
  Wamei += V["amef"]*T["fi"];
  Wamei += .5*V["mnef"]*T["afin"];

  CTF_Tensor tWamij(*V["amij"].parent);
  CTF_Idx_Tensor Wamij(&tWamij,"amij");
  Wamij += V["amij"];
  Wamij += V["amei"]*T["ej"];
  Wamij += V["amef"]*T["efij"];

  CTF_Tensor tZai(*V["ai"].parent);
  CTF_Idx_Tensor Zai(&tZai,"ai");
  Zai += V["ai"];
  Zai -= Fmi*T["am"];
  Zai += V["ae"]*T["ei"];
  Zai += V["amei"]*T["em"];
  Zai += V["aeim"]*Fme;
  Zai += .5*V["amef"]*T21["efim"];
  Zai -= .5*Wmnei*T21["eamn"];

  CTF_Tensor tZabij(*V["abij"].parent);
  CTF_Idx_Tensor Zabij(&tZabij,"abij");
  Zabij += V["abij"];
  Zabij += V["abei"]*T["ej"];
  Zabij += Wamei*T["ebmj"];
  Zabij -= Wamij*T["bm"];
  Zabij += Fae*T["ebij"];
  Zabij -= Fmi*T["abmj"];
  Zabij += .5*V["abef"]*T21["efij"];
  Zabij += .5*Wmnij*T21["abmn"];

  CTF_fctr fctr;
  fctr.func_ptr = ÷

  CTF_Tensor Dai(2, V.ai.len, V.ai.sym, *V.dw);
  int sh_sym[4] = {SH, NS, SH, NS};
  CTF_Tensor Dabij(4, V.abij.len, sh_sym, *V.dw);
  Dai["ai"] += V["i"];
  Dai["ai"] -= V["a"];

  Dabij["abij"] += V["i"];
  Dabij["abij"] += V["j"];
  Dabij["abij"] -= V["a"];
  Dabij["abij"] -= V["b"];

  T.ai.contract(1.0, *(Zai.parent), "ai", Dai, "ai", 0.0, "ai", fctr);
  T.abij.contract(1.0, *(Zabij.parent), "abij", Dabij, "abij", 0.0, "abij", fctr);
}

#ifndef TEST_SUITE

char* getCmdOption(char ** begin,
                   char ** end,
                   const   std::string & option){
  char ** itr = std::find(begin, end, option);
  if (itr != end && ++itr != end){
    return *itr;
  }
  return 0;
}

int main(int argc, char ** argv){
  int rank, np, niter, no, nv, i;
  int const in_num = argc;
  char ** input_str = argv;

  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &np);

  if (getCmdOption(input_str, input_str+in_num, "-no")){
    no = atoi(getCmdOption(input_str, input_str+in_num, "-no"));
    if (no < 0) no= 4;
  } else no = 4;
  if (getCmdOption(input_str, input_str+in_num, "-nv")){
    nv = atoi(getCmdOption(input_str, input_str+in_num, "-nv"));
    if (nv < 0) nv = 6;
  } else nv = 6;
  if (getCmdOption(input_str, input_str+in_num, "-niter")){
    niter = atoi(getCmdOption(input_str, input_str+in_num, "-niter"));
    if (niter < 0) niter = 1;
  } else niter = 1;

  {
    CTF_World dw(argc, argv);
    {
      Integrals V(no, nv, dw);
      V.fill_rand();
      Amplitudes T(no, nv, dw);
      for (i=0; i<niter; i++){
        T.fill_rand();
        double d = MPI_Wtime();
        ccsd(V,T);
        if (rank == 0)
          printf("Completed %dth CCSD iteration in time = %lf, |T| is %lf\n",
                  i, MPI_Wtime()-d, T.ai.norm2()+T.abij.norm2());
        else {
          T.ai.norm2();
          T.abij.norm2();
        }
        T["ai"] = (1./T.ai.norm2())*T["ai"];
        T["abij"] = (1./T.abij.norm2())*T["abij"];
      }
    }
  }

  MPI_Finalize();
  return 0;
}
/**
 * @}
 * @}
 */

#endif

<|endoftext|>


<commit_before><commit_msg>svidl: write dependencies with cygwin paths<commit_after><|endoftext|>


<commit_before>// [[Rcpp::depends(BH)]]

#include "Random.h"

#include <boost/random/uniform_01.hpp>
#include <boost/random/uniform_real_distribution.hpp>
#include <boost/random/normal_distribution.hpp>
#include <boost/random/poisson_distribution.hpp>
#include <boost/random/exponential_distribution.hpp>
#include <boost/random/mersenne_twister.hpp>

#include <boost/math/distributions/normal.hpp>
#include <boost/math/distributions/exponential.hpp>
#include <boost/math/distributions/gamma.hpp>

#include <stdint.h>

#define Q_GAMMA_THRESHOLD 0.000001f
#define Q_GAMMA_MIN_VALUE 0.0

typedef boost::random::mt19937 RNGType;
//typedef boost::random::mt11213b RNGType; // should be faster

static RNGType rng;

void gaps::random::save(Archive &ar)
{
    ar << rng;
}

void gaps::random::load(Archive &ar)
{
    ar >> rng;
}

void gaps::random::setSeed(uint32_t seed)
{
    rng.seed(seed);
}

float gaps::random::normal(float mean, float var)
{
    boost::random::normal_distribution<float> dist(mean, var);
    return dist(rng);
}

int gaps::random::poisson(float lambda)
{
    boost::random::poisson_distribution<> dist(lambda);
    return dist(rng);
}

float gaps::random::exponential(float lambda)
{
    boost::random::exponential_distribution<> dist(lambda);
    return dist(rng);
}

float gaps::random::uniform()
{
    boost::random::uniform_01<RNGType&> dist(rng); // could be moved out
    return dist();
}

float gaps::random::uniform(float a, float b)
{
    if (a == b)
    {
        return a;
    }
    else
    {
        boost::random::uniform_real_distribution<> dist(a,b);
        return dist(rng);
    }
}

uint64_t gaps::random::uniform64()
{
    boost::random::uniform_int_distribution<uint64_t> dist(0,
        std::numeric_limits<uint64_t>::max());
    return dist(rng);
}

uint64_t gaps::random::uniform64(uint64_t a, uint64_t b)
{
    if (a == b)
    {
        return a;
    }
    else
    {
        boost::random::uniform_int_distribution<uint64_t> dist(a,b);
        return dist(rng);
    }
}

float gaps::random::d_gamma(float d, float shape, float scale)
{
    boost::math::gamma_distribution<> gam(shape, scale);
    return pdf(gam, d);
}

float gaps::random::p_gamma(float p, float shape, float scale)
{
    boost::math::gamma_distribution<> gam(shape, scale);
    return cdf(gam, p);
}

float gaps::random::q_gamma(float q, float shape, float scale)
{
    if (q < Q_GAMMA_THRESHOLD)
    {
        return Q_GAMMA_MIN_VALUE;
    }
    else
    {
        boost::math::gamma_distribution<> gam(shape, scale);
        return quantile(gam, q);
    }
}

float gaps::random::d_norm(float d, float mean, float sd)
{
    boost::math::normal_distribution<> norm(mean, sd);
    return pdf(norm, d);
}

float gaps::random::q_norm(float q, float mean, float sd)
{
    boost::math::normal_distribution<> norm(mean, sd);
    return quantile(norm, q);
}

float gaps::random::p_norm(float p, float mean, float sd)
{
    boost::math::normal_distribution<> norm(mean, sd);
    return cdf(norm, p);
}
<commit_msg>make uniform open interval to avoid errors<commit_after>// [[Rcpp::depends(BH)]]

#include "Random.h"

#include <boost/random/uniform_01.hpp>
#include <boost/random/uniform_real_distribution.hpp>
#include <boost/random/normal_distribution.hpp>
#include <boost/random/poisson_distribution.hpp>
#include <boost/random/exponential_distribution.hpp>
#include <boost/random/mersenne_twister.hpp>

#include <boost/math/distributions/normal.hpp>
#include <boost/math/distributions/exponential.hpp>
#include <boost/math/distributions/gamma.hpp>

#include <stdint.h>

#define Q_GAMMA_THRESHOLD 0.000001f
#define Q_GAMMA_MIN_VALUE 0.0

typedef boost::random::mt19937 RNGType;
//typedef boost::random::mt11213b RNGType; // should be faster

static RNGType rng;

void gaps::random::save(Archive &ar)
{
    ar << rng;
}

void gaps::random::load(Archive &ar)
{
    ar >> rng;
}

void gaps::random::setSeed(uint32_t seed)
{
    rng.seed(seed);
}

float gaps::random::normal(float mean, float var)
{
    boost::random::normal_distribution<float> dist(mean, var);
    return dist(rng);
}

int gaps::random::poisson(float lambda)
{
    boost::random::poisson_distribution<> dist(lambda);
    return dist(rng);
}

float gaps::random::exponential(float lambda)
{
    boost::random::exponential_distribution<> dist(lambda);
    return dist(rng);
}

float gaps::random::uniform()
{
    boost::random::uniform_01<RNGType&> dist(rng); // could be moved out
    return dist();
}

// open interval
float gaps::random::uniform(float a, float b)
{
    if (a == b)
    {
        return a;
    }
    else
    {
        boost::random::uniform_real_distribution<> dist(a,b);
        float result = dist(rng);
        while (result == b)
        {
            result = dist(rng);
        }
        return result;
    }
}

uint64_t gaps::random::uniform64()
{
    boost::random::uniform_int_distribution<uint64_t> dist(0,
        std::numeric_limits<uint64_t>::max());
    return dist(rng);
}

uint64_t gaps::random::uniform64(uint64_t a, uint64_t b)
{
    if (a == b)
    {
        return a;
    }
    else
    {
        boost::random::uniform_int_distribution<uint64_t> dist(a,b);
        return dist(rng);
    }
}

float gaps::random::d_gamma(float d, float shape, float scale)
{
    boost::math::gamma_distribution<> gam(shape, scale);
    return pdf(gam, d);
}

float gaps::random::p_gamma(float p, float shape, float scale)
{
    boost::math::gamma_distribution<> gam(shape, scale);
    return cdf(gam, p);
}

float gaps::random::q_gamma(float q, float shape, float scale)
{
    if (q < Q_GAMMA_THRESHOLD)
    {
        return Q_GAMMA_MIN_VALUE;
    }
    else
    {
        boost::math::gamma_distribution<> gam(shape, scale);
        return quantile(gam, q);
    }
}

float gaps::random::d_norm(float d, float mean, float sd)
{
    boost::math::normal_distribution<> norm(mean, sd);
    return pdf(norm, d);
}

float gaps::random::q_norm(float q, float mean, float sd)
{
    boost::math::normal_distribution<> norm(mean, sd);
    return quantile(norm, q);
}

float gaps::random::p_norm(float p, float mean, float sd)
{
    boost::math::normal_distribution<> norm(mean, sd);
    return cdf(norm, p);
}
<|endoftext|>


<commit_before>#include"combination.h"
#include<algorithm>
#include<functional>	//function
#include<numeric>	//iota
#include<type_traits>	//make_unsigned
#include"math.h"

namespace nMath
{
	template<class T>
	T C(const T n,const T k)
	{
		using namespace std;
		//To speed up, I do not call factorial.
		T start{max(n-k,k)};
		vector<T> numerator(n-start),divisor(n-start);
		iota(begin(numerator),end(numerator),start+1);
		iota(begin(divisor),end(divisor),1);
		T product{1};
		for(auto &val:numerator)
		{
			for(auto &val2:numerator)
			{
				const T temp{gcd(val,val2)};
				if(temp!=1)
				{
					val/=temp;
					val2/=temp;
				}
			}
			product*=val;
		}
		accumulate(begin(divisor),end(divisor),product,[](const auto init,const auto val){return init/val;});
		return product;
	}

	template<class InIter>
	std::vector<std::vector<typename std::iterator_traits<InIter>::value_type>> combination(InIter gbegin,const InIter gend,const std::size_t take_count)
	{
		using namespace std;
		typedef vector<vector<typename iterator_traits<InIter>::value_type>> Vec;
		function<void(InIter,InIter,Vec &,size_t)> combination_{[&,gend](InIter begin,const InIter end,Vec &vec,const size_t level){
			while(begin!=end)
			{
				vec.back().emplace_back(*begin);
				if(end!=gend)
					combination_(next(begin),next(end),vec,level+1);
				++begin;
				if(begin!=end)
					vec.emplace_back(vec.back().begin(),next(vec.back().begin(),level));
			}
		}};
		const auto dis{make_unsigned<ptrdiff_t>::type(distance(gbegin,gend))};
		if(!dis||dis<take_count)
			return {};
		Vec vec(1);
		vec.reserve(C<make_unsigned<ptrdiff_t>::type>(dis,take_count));
		combination_(gbegin,prev(gend,take_count-1),vec,0);
		return vec;
	}
}<commit_msg>update combination (begin, end, static_cast)<commit_after>#include"combination.h"
#include<algorithm>
#include<functional>	//function
#include<numeric>	//iota
#include<type_traits>	//make_unsigned
#include"math.h"

namespace nMath
{
	template<class T>
	T C(const T n,const T k)
	{
		using namespace std;
		//To speed up, I do not call factorial.
		T start{max(n-k,k)};
		vector<T> numerator(n-start),divisor(n-start);
		iota(begin(numerator),end(numerator),start+1);
		iota(begin(divisor),end(divisor),1);
		T product{1};
		for(auto &val:numerator)
		{
			for(auto &val2:numerator)
			{
				const T temp{gcd(val,val2)};
				if(temp!=1)
				{
					val/=temp;
					val2/=temp;
				}
			}
			product*=val;
		}
		accumulate(begin(divisor),end(divisor),product,[](const auto init,const auto val){return init/val;});
		return product;
	}

	template<class InIter>
	std::vector<std::vector<typename std::iterator_traits<InIter>::value_type>> combination(InIter gbegin,const InIter gend,const std::size_t take_count)
	{
		using namespace std;
		typedef vector<vector<typename iterator_traits<InIter>::value_type>> Vec;
		function<void(InIter,InIter,Vec &,size_t)> combination_{[&,gend](InIter begin,const InIter end,Vec &vec,const size_t level){
			while(begin!=end)
			{
				vec.back().emplace_back(*begin);
				if(end!=gend)
					combination_(next(begin),next(end),vec,level+1);
				++begin;
				if(begin!=end)
					vec.emplace_back(begin(vec.back()),next(begin(vec.back()),level));
			}
		}};
		const auto dis{make_unsigned<ptrdiff_t>::type(distance(gbegin,gend))};
		if(!dis||dis<take_count)
			return {};
		Vec vec(1);
		vec.reserve(C(dis,static_cast<make_unsigned<ptrdiff_t>::type>(take_count)));
		combination_(gbegin,prev(gend,take_count-1),vec,0);
		return vec;
	}
}<|endoftext|>


<commit_before>//===-- SelectionDAGPrinter.cpp - Implement SelectionDAG::viewGraph() -----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This implements the SelectionDAG::viewGraph method.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Function.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/config.h"
#include <fstream>
using namespace llvm;

namespace llvm {
  template<>
  struct DOTGraphTraits<SelectionDAG*> : public DefaultDOTGraphTraits {
    static std::string getGraphName(const SelectionDAG *G) {
      return G->getMachineFunction().getFunction()->getName();
    }

    static bool renderGraphFromBottomUp() {
      return true;
    }

    static std::string getNodeLabel(const SDNode *Node,
                                    const SelectionDAG *Graph);
    static std::string getNodeAttributes(const SDNode *N) {
      return "shape=Mrecord";
    }

    static void addCustomGraphFeatures(SelectionDAG *G,
                                       GraphWriter<SelectionDAG*> &GW) {
      GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
      GW.emitEdge(0, -1, G->getRoot().Val, -1, "");
    }
  };
}

std::string DOTGraphTraits<SelectionDAG*>::getNodeLabel(const SDNode *Node,
                                                        const SelectionDAG *G) {
  std::string Op = Node->getOperationName();

  for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i) {
    switch (Node->getValueType(i)) {
    default: Op += ":unknownvt!"; break;
    case MVT::Other: Op += ":ch"; break;
    case MVT::i1:    Op += ":i1"; break;
    case MVT::i8:    Op += ":i8"; break;
    case MVT::i16:   Op += ":i16"; break;
    case MVT::i32:   Op += ":i32"; break;
    case MVT::i64:   Op += ":i64"; break;
    case MVT::i128:  Op += ":i128"; break;
    case MVT::f32:   Op += ":f32"; break;
    case MVT::f64:   Op += ":f64"; break;
    case MVT::f80:   Op += ":f80"; break;
    case MVT::f128:  Op += ":f128"; break;
    case MVT::isVoid: Op += ":void"; break;
    }
  }

  if (const ConstantSDNode *CSDN = dyn_cast<ConstantSDNode>(Node)) {
    Op += ": " + utostr(CSDN->getValue());
  } else if (const ConstantFPSDNode *CSDN = dyn_cast<ConstantFPSDNode>(Node)) {
    Op += ": " + ftostr(CSDN->getValue());
  } else if (const GlobalAddressSDNode *GADN =
             dyn_cast<GlobalAddressSDNode>(Node)) {
    Op += ": " + GADN->getGlobal()->getName();
  } else if (const FrameIndexSDNode *FIDN = dyn_cast<FrameIndexSDNode>(Node)) {
    Op += " " + itostr(FIDN->getIndex());
  } else if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Node)){
    Op += "<" + utostr(CP->getIndex()) + ">";
  } else if (const BasicBlockSDNode *BBDN = dyn_cast<BasicBlockSDNode>(Node)) {
    Op = "BB: ";
    const Value *LBB = (const Value*)BBDN->getBasicBlock()->getBasicBlock();
    if (LBB)
      Op += LBB->getName();
    //Op += " " + (const void*)BBDN->getBasicBlock();
  } else if (const RegSDNode *C2V = dyn_cast<RegSDNode>(Node)) {
    Op += " #" + utostr(C2V->getReg());
  } else if (const ExternalSymbolSDNode *ES =
             dyn_cast<ExternalSymbolSDNode>(Node)) {
    Op += "'" + std::string(ES->getSymbol()) + "'";
  } else if (const SrcValueSDNode *M = dyn_cast<SrcValueSDNode>(Node)) {
    if (M->getValue())
      Op += "<" + M->getValue()->getName() + ":" + itostr(M->getOffset()) + ">";
    else
      Op += "<null:" + itostr(M->getOffset()) + ">";
  }
  return Op;
}

/// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
/// rendered using 'dot'.
///
void SelectionDAG::viewGraph() {
// This code is only for debugging!
#ifndef NDEBUG
  std::string Filename = "/tmp/dag." +
    getMachineFunction().getFunction()->getName() + ".dot";
  std::cerr << "Writing '" << Filename << "'... ";
  std::ofstream F(Filename.c_str());

  if (!F) {
    std::cerr << "  error opening file for writing!\n";
    return;
  }

  WriteGraph(F, this);
  F.close();
  std::cerr << "\n";

#ifdef HAVE_GRAPHVIZ
  std::cerr << "Running 'Graphviz' program... " << std::flush;
  if (system((LLVM_PATH_GRAPHVIZ " " + Filename).c_str())) {
    std::cerr << "Error viewing graph: 'Graphviz' not in path?\n";
  } else {
    system(("rm " + Filename).c_str());
    return;
  }
#endif  // HAVE_GRAPHVIZ

#ifdef HAVE_GV
  std::cerr << "Running 'dot' program... " << std::flush;
  if (system(("dot -Tps -Nfontname=Courier -Gsize=7.5,10 " + Filename
              + " > /tmp/dag.tempgraph.ps").c_str())) {
    std::cerr << "Error viewing graph: 'dot' not in path?\n";
  } else {
    std::cerr << "\n";
    system(LLVM_PATH_GV " /tmp/dag.tempgraph.ps");
  }
  system(("rm " + Filename + " /tmp/dag.tempgraph.ps").c_str());
  return;
#endif  // HAVE_GV
#endif  // NDEBUG
  std::cerr << "SelectionDAG::viewGraph is only available in debug builds on "
            << "systems with Graphviz or gv!\n";

#ifndef NDEBUG
  system(("rm " + Filename).c_str());
#endif
}
<commit_msg>Use a extant helper to do this.<commit_after>//===-- SelectionDAGPrinter.cpp - Implement SelectionDAG::viewGraph() -----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This implements the SelectionDAG::viewGraph method.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Function.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/config.h"
#include <fstream>
using namespace llvm;

namespace llvm {
  template<>
  struct DOTGraphTraits<SelectionDAG*> : public DefaultDOTGraphTraits {
    static std::string getGraphName(const SelectionDAG *G) {
      return G->getMachineFunction().getFunction()->getName();
    }

    static bool renderGraphFromBottomUp() {
      return true;
    }

    static std::string getNodeLabel(const SDNode *Node,
                                    const SelectionDAG *Graph);
    static std::string getNodeAttributes(const SDNode *N) {
      return "shape=Mrecord";
    }

    static void addCustomGraphFeatures(SelectionDAG *G,
                                       GraphWriter<SelectionDAG*> &GW) {
      GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
      GW.emitEdge(0, -1, G->getRoot().Val, -1, "");
    }
  };
}

std::string DOTGraphTraits<SelectionDAG*>::getNodeLabel(const SDNode *Node,
                                                        const SelectionDAG *G) {
  std::string Op = Node->getOperationName(G);

  for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i)
    if (Node->getValueType(i) == MVT::Other)
      Op += ":ch";
    else
      Op = Op + ":" + MVT::getValueTypeString(Node->getValueType(i));

  if (const ConstantSDNode *CSDN = dyn_cast<ConstantSDNode>(Node)) {
    Op += ": " + utostr(CSDN->getValue());
  } else if (const ConstantFPSDNode *CSDN = dyn_cast<ConstantFPSDNode>(Node)) {
    Op += ": " + ftostr(CSDN->getValue());
  } else if (const GlobalAddressSDNode *GADN =
             dyn_cast<GlobalAddressSDNode>(Node)) {
    Op += ": " + GADN->getGlobal()->getName();
  } else if (const FrameIndexSDNode *FIDN = dyn_cast<FrameIndexSDNode>(Node)) {
    Op += " " + itostr(FIDN->getIndex());
  } else if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Node)){
    Op += "<" + utostr(CP->getIndex()) + ">";
  } else if (const BasicBlockSDNode *BBDN = dyn_cast<BasicBlockSDNode>(Node)) {
    Op = "BB: ";
    const Value *LBB = (const Value*)BBDN->getBasicBlock()->getBasicBlock();
    if (LBB)
      Op += LBB->getName();
    //Op += " " + (const void*)BBDN->getBasicBlock();
  } else if (const RegSDNode *C2V = dyn_cast<RegSDNode>(Node)) {
    Op += " #" + utostr(C2V->getReg());
  } else if (const ExternalSymbolSDNode *ES =
             dyn_cast<ExternalSymbolSDNode>(Node)) {
    Op += "'" + std::string(ES->getSymbol()) + "'";
  } else if (const SrcValueSDNode *M = dyn_cast<SrcValueSDNode>(Node)) {
    if (M->getValue())
      Op += "<" + M->getValue()->getName() + ":" + itostr(M->getOffset()) + ">";
    else
      Op += "<null:" + itostr(M->getOffset()) + ">";
  }
  return Op;
}

/// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
/// rendered using 'dot'.
///
void SelectionDAG::viewGraph() {
// This code is only for debugging!
#ifndef NDEBUG
  std::string Filename = "/tmp/dag." +
    getMachineFunction().getFunction()->getName() + ".dot";
  std::cerr << "Writing '" << Filename << "'... ";
  std::ofstream F(Filename.c_str());

  if (!F) {
    std::cerr << "  error opening file for writing!\n";
    return;
  }

  WriteGraph(F, this);
  F.close();
  std::cerr << "\n";

#ifdef HAVE_GRAPHVIZ
  std::cerr << "Running 'Graphviz' program... " << std::flush;
  if (system((LLVM_PATH_GRAPHVIZ " " + Filename).c_str())) {
    std::cerr << "Error viewing graph: 'Graphviz' not in path?\n";
  } else {
    system(("rm " + Filename).c_str());
    return;
  }
#endif  // HAVE_GRAPHVIZ

#ifdef HAVE_GV
  std::cerr << "Running 'dot' program... " << std::flush;
  if (system(("dot -Tps -Nfontname=Courier -Gsize=7.5,10 " + Filename
              + " > /tmp/dag.tempgraph.ps").c_str())) {
    std::cerr << "Error viewing graph: 'dot' not in path?\n";
  } else {
    std::cerr << "\n";
    system(LLVM_PATH_GV " /tmp/dag.tempgraph.ps");
  }
  system(("rm " + Filename + " /tmp/dag.tempgraph.ps").c_str());
  return;
#endif  // HAVE_GV
#endif  // NDEBUG
  std::cerr << "SelectionDAG::viewGraph is only available in debug builds on "
            << "systems with Graphviz or gv!\n";

#ifndef NDEBUG
  system(("rm " + Filename).c_str());
#endif
}
<|endoftext|>


<commit_before>#pragma once

#include <stdint.h>
#include <libusb.h>
#include <QMutex>

#include "Radio.hpp"

// FIXME - This needs to go somewhere common to this code, the robot firmware,
// and the base station test code.
const unsigned int Forward_Size = 55;
const unsigned int Reverse_Size = 7;

/**
 * @brief Radio IO with real robots
 *
 * @details This class provides us the ability to communicate with real robots
 *     using our own radio protocol. The radio sends one large packet to all of
 *     the robots at once that contains the data in each robot's radioTx packet.
 *     Note that it isn't sent in protobuf format though, it's sent straight-up
 *     data to avoid the overhead of protobuf.  Robots respond individually in
 *     order of their shell numbers in a set time slot.  The bot with the lowest
 *     shell number replies in the first time slot, and so on.  This ensures
 *     that robots don't jam each other's communication.
 */
class USBRadio : public Radio {
public:
    // n identifies which base station to use.
    USBRadio();
    ~USBRadio();

    virtual bool isOpen() const override;
    virtual void send(Packet::RadioTx& packet) override;
    virtual void receive() override;

    virtual void channel(int n) override;
    void switchTeam(bool) override {}

protected:
    libusb_context* _usb_context;
    libusb_device_handle* _device;

    // These transfers are used to receive packets.
    // Try increasing this constant for larger RX packet throughput.
    static const int NumRXTransfers = 4;
    libusb_transfer* _rxTransfers[NumRXTransfers];
    uint8_t _rxBuffers[NumRXTransfers][Reverse_Size + 2];

    QMutex _mutex;
    int _sequence;
    bool _printedError;

    static void rxCompleted(struct libusb_transfer* transfer);
    void handleRxData(uint8_t* buf);

    bool open();

    // Low level operations
    void command(uint8_t cmd);
    void write(uint8_t reg, uint8_t value);
    uint8_t read(uint8_t reg);
};
<commit_msg>comment<commit_after>#pragma once

#include <stdint.h>
#include <libusb.h>
#include <QMutex>

#include "Radio.hpp"

// FIXME - This needs to go somewhere common to this code, the robot firmware,
// and the base station test code.
const unsigned int Forward_Size = 55;
const unsigned int Reverse_Size = 7;

/**
 * @brief Radio IO with real robots
 *
 * @details This class provides us the ability to communicate with real robots
 *     using our own radio protocol. The radio sends one large packet to all of
 *     the robots at once that contains the data in each robot's radioTx packet.
 *     Note that it isn't sent in protobuf format though, it's sent straight-up
 *     data to avoid the overhead of protobuf.  Robots respond individually in
 *     order of their shell numbers in a set time slot.  The bot with the lowest
 *     shell number replies in the first time slot, and so on.  This ensures
 *     that robots don't jam each other's communication.
 */
class USBRadio : public Radio {
public:
    USBRadio();
    ~USBRadio();

    virtual bool isOpen() const override;
    virtual void send(Packet::RadioTx& packet) override;
    virtual void receive() override;

    virtual void channel(int n) override;
    void switchTeam(bool) override {}

protected:
    libusb_context* _usb_context;
    libusb_device_handle* _device;

    // These transfers are used to receive packets.
    // Try increasing this constant for larger RX packet throughput.
    static const int NumRXTransfers = 4;
    libusb_transfer* _rxTransfers[NumRXTransfers];
    uint8_t _rxBuffers[NumRXTransfers][Reverse_Size + 2];

    QMutex _mutex;
    int _sequence;
    bool _printedError;

    static void rxCompleted(struct libusb_transfer* transfer);
    void handleRxData(uint8_t* buf);

    bool open();

    // Low level operations
    void command(uint8_t cmd);
    void write(uint8_t reg, uint8_t value);
    uint8_t read(uint8_t reg);
};
<|endoftext|>


<commit_before>// C++ truss implementation

// TODO: switch to a better logging framework
#include <iostream>
#include <fstream>
#include "trussapi.h"
#include "truss.h"
#include "terra.h"

using namespace trss;

Interpreter::Interpreter(int id, const char* name) {
		_thread = NULL;
		_messageLock = SDL_CreateMutex();
		_execLock = SDL_CreateMutex();
		_terraState = NULL;
		_running = false;
		_autoExecute = true;
		_executeOnMessage = false;
		_executeNext = false;
		_name = name;
		_ID = id;
		_curMessages = new std::vector < trss_message* > ;
		_fetchedMessages = new std::vector < trss_message* >;
}

Interpreter::~Interpreter() {
	// Nothing special to do
}

const std::string& Interpreter::getName() const {
	return _name;
}

int Interpreter::getID() const {
	return _ID;
}

void Interpreter::attachAddon(Addon* addon) {
	if(!_running && _thread == NULL) {
		_addons.push_back(addon);
	} else {
		std::cout << "Cannot attach addon to running interpreter.\n";
		delete addon;
	}
}

int Interpreter::numAddons() {
	return (int)(_addons.size());
}

Addon* Interpreter::getAddon(int idx) {
	if(idx >= 0 && idx < _addons.size()) {
		return _addons[idx];
	} else {
		return NULL;
	}
}

int run_interpreter_thread(void* interpreter) {
	Interpreter* target = (Interpreter*)interpreter;
	target->_threadEntry();
	return 0;
}

void Interpreter::start(const char* arg) {
	if(_thread != NULL || _running) {
		std::cout << "Can't start interpreter twice: already running\n";
		return;
	}

	_running = true;
	_thread = SDL_CreateThread(run_interpreter_thread,
								_name.c_str(),
								(void*)this);
}

void Interpreter::startUnthreaded(const char* arg) {
	if(_thread != NULL || _running) {
		std::cout << "Can't start interpreter twice: already running\n";
		return;
	}

	_running = true;
	_threadEntry();
}

void Interpreter::stop() {
	_running = false;
}

void Interpreter::execute() {
	std::cout << "Interpreter::execute not implemented!\n";
	// TODO: make this do something
}

void Interpreter::_threadEntry() {
	_terraState = luaL_newstate();
	luaL_openlibs(_terraState);
	terra_Options* opts = new terra_Options;
	opts->verbose = 2; // very verbose
	opts->debug = 1; // debug enabled
	terra_initwithoptions(_terraState, opts);
	delete opts; // not sure if necessary or desireable

	// load and execute the bootstrap script
	trss_message* bootstrap = trss_load_file("bootstrap.t", TRSS_CORE_PATH);
	terra_loadbuffer(_terraState,
                     (char*)bootstrap->data,
                     bootstrap->data_length,
                     "bootstrap.t");
	int res = lua_pcall(_terraState, 0, 0, 0);
	if(res != 0) {
		std::cout << "Error bootstrapping interpreter: "
				  << lua_tostring(_terraState, -1) << std::endl;
	}

	// Init all the addons
	for(size_t i = 0; i < _addons.size(); ++i) {
		_addons[i]->init(this);
	}

	// Call init
	_safeLuaCall("_core_init");

	double dt = 1.0 / 60.0; // just fudge this at the moment

	// Enter thread main loop
	while(_running) {
		// update addons
		for(unsigned int i = 0; i < _addons.size(); ++i) {
			_addons[i]->update(dt);
		}

		// update lua
		_safeLuaCall("_core_update");
	}

	// Shutdown
	std::cout << "Shuttind down.\n";
	// TODO: actually shutdown stuff here
}

void Interpreter::sendMessage(trss_message* message) {
	SDL_LockMutex(_messageLock);
	trss_acquire_message(message);
	_curMessages->push_back(message);
	SDL_UnlockMutex(_messageLock);
}

int Interpreter::fetchMessages() {
	SDL_LockMutex(_messageLock);
	// swap messages
	std::vector<trss_message*>* temp = _curMessages;
	_curMessages = _fetchedMessages;
	_fetchedMessages = temp;

	// clear the 'current' messages (i.e., the old fetched messages)
	for(unsigned int i = 0; i < _curMessages->size(); ++i) {
		trss_release_message((*_curMessages)[i]);
	}
	_curMessages->clear();
	size_t numMessages = _fetchedMessages->size();

	SDL_UnlockMutex(_messageLock);
	return (int)(numMessages);
}

trss_message* Interpreter::getMessage(int index) {
	// Note: don't need to lock because only 'our' thread
	// should call fetchMessages (which is the only other function
	// that touches _fetchedMessages)
	return (*_fetchedMessages)[index];
}

void Interpreter::_safeLuaCall(const char* funcname, const char* argstr) {
	int nargs = 0;
	lua_getglobal(_terraState, funcname);
	if(argstr != NULL) {
		nargs = 1;
		lua_pushstring(_terraState, argstr);
	}
	int res = lua_pcall(_terraState, nargs, 0, 0);
	if(res != 0) {
		std::cout << lua_tostring(_terraState, -1) << std::endl;
	}
}

void trss_log(int log_level, const char* str){
	Core::getCore()->logMessage(log_level, str);
}

trss_message* trss_load_file(const char* filename, int path_type){
	return Core::getCore()->loadFile(filename, path_type);
}

/* Note that when saving the message_type field is not saved */
int trss_save_file(const char* filename, int path_type, trss_message* data){
	Core::getCore()->saveFile(filename, path_type, data);
	return 0; // TODO: actually check for errors
}

/* Interpreter management functions */
int trss_spawn_interpreter(const char* name){
	Interpreter* spawned = Core::getCore()->spawnInterpreter(name);
	return spawned->getID();
}

void trss_start_interpreter(trss_interpreter_id target_id, const char* msgstr) {
	Core::getCore()->getInterpreter(target_id)->start(msgstr);
}

void trss_stop_interpreter(trss_interpreter_id target_id){
	Core::getCore()->getInterpreter(target_id)->stop();
}

void trss_execute_interpreter(trss_interpreter_id target_id){
	return Core::getCore()->getInterpreter(target_id)->execute();
}

int trss_find_interpreter(const char* name){
	return Core::getCore()->getNamedInterpreter(name)->getID();
}

void trss_send_message(trss_interpreter_id dest, trss_message* message){
	Core::getCore()->dispatchMessage(dest, message);
}

int trss_fetch_messages(trss_interpreter_id idx){
	Interpreter* interpreter = Core::getCore()->getInterpreter(idx);
	if(interpreter) {
		return interpreter->fetchMessages();
	} else {
		return -1;
	}
}

trss_message* trss_get_message(trss_interpreter_id idx, int message_index){
	Interpreter* interpreter = Core::getCore()->getInterpreter(idx);
	if(interpreter) {
		return interpreter->getMessage(message_index);
	} else {
		return NULL;
	}
}

int trss_get_addon_count(trss_interpreter_id target_id) {
	Interpreter* interpreter = Core::getCore()->getInterpreter(target_id);
	if(interpreter) {
		return interpreter->numAddons();
	} else {
		return -1;
	}
}

Addon* trss_get_addon(trss_interpreter_id target_id, int addon_idx) {
	Interpreter* interpreter = Core::getCore()->getInterpreter(target_id);
	if(interpreter) {
		return interpreter->getAddon(addon_idx);
	} else {
		return NULL;
	}
}

const char* trss_get_addon_header(trss_interpreter_id target_id, int addon_idx) {
	Addon* addon = trss_get_addon(target_id, addon_idx);
	if(addon) {
		return addon->getCHeader().c_str();
	} else {
		return "";
	}
}

/* Message management functions */
trss_message* trss_create_message(unsigned int data_length){
	return Core::getCore()->allocateMessage(data_length);
}

void trss_acquire_message(trss_message* msg){
	++(msg->_refcount);
}

void trss_release_message(trss_message* msg){
	--(msg->_refcount);
	if(msg->_refcount <= 0) {
		Core::getCore()->deallocateMessage(msg);
	}
}

trss_message* trss_copy_message(trss_message* src){
	trss_message* newmsg = Core::getCore()->allocateMessage(src->data_length);
	newmsg->message_type = src->message_type;
	memcpy(newmsg->data, src->data, newmsg->data_length);
	return newmsg;
}

Core* core() {
	return Core::getCore();
}

Core* Core::__core = NULL;

Core* Core::getCore() {
	if(__core == NULL) {
		__core = new Core();
	}
	return __core;
}

void Core::logMessage(int log_level, const char* msg) {
	SDL_LockMutex(_coreLock);
	// just dump to standard out for the moment
	std::cout << log_level << "|" << msg << std::endl;
	SDL_UnlockMutex(_coreLock);
}

Interpreter* Core::getInterpreter(int idx){
	Interpreter* ret = NULL;
	SDL_LockMutex(_coreLock);
	if(idx >= 0 && idx < _interpreters.size()) {
		ret = _interpreters[idx];
	}
	SDL_UnlockMutex(_coreLock);
	return ret;
}

Interpreter* Core::getNamedInterpreter(const char* name){
	std::string sname(name);
	Interpreter* ret = NULL;
	SDL_LockMutex(_coreLock);
	for(size_t i = 0; i < _interpreters.size(); ++i) {
		if(_interpreters[i]->getName() == sname) {
			ret = _interpreters[i];
			break;
		}
	}
	SDL_UnlockMutex(_coreLock);
	return ret;
}

Interpreter* Core::spawnInterpreter(const char* name){
	SDL_LockMutex(_coreLock);
	Interpreter* interpreter = new Interpreter((int)(_interpreters.size()), name);
	_interpreters.push_back(interpreter);
	SDL_UnlockMutex(_coreLock);
	return interpreter;
}

int Core::numInterpreters(){
	int ret = 0;
	SDL_LockMutex(_coreLock);
	ret = (int)(_interpreters.size());
	SDL_UnlockMutex(_coreLock);
	return ret;
}

void Core::dispatchMessage(int targetIdx, trss_message* msg){
	Interpreter* interpreter = getInterpreter(targetIdx);
	if(interpreter) {
		interpreter->sendMessage(msg);
	}
}

void Core::acquireMessage(trss_message* msg){
	SDL_LockMutex(_coreLock);
	++(msg->_refcount);
	SDL_UnlockMutex(_coreLock);
}

void Core::releaseMessage(trss_message* msg){
	SDL_LockMutex(_coreLock);
	--(msg->_refcount);
	if(msg->_refcount <= 0) {
		deallocateMessage(msg);
	}
	SDL_UnlockMutex(_coreLock);
}

trss_message* Core::copyMessage(trss_message* src){
	SDL_LockMutex(_coreLock);
	trss_message* newmsg = allocateMessage(src->data_length);
	newmsg->message_type = src->message_type;
	memcpy(newmsg->data, src->data, newmsg->data_length);
	SDL_UnlockMutex(_coreLock);
	return newmsg;
}

trss_message* Core::allocateMessage(int dataLength){
	trss_message* ret = new trss_message;
	ret->data = new unsigned char[dataLength];
	ret->data_length = dataLength;
	ret->_refcount = 1;
	return ret;
}

void Core::deallocateMessage(trss_message* msg){
	delete[] msg->data;
	delete msg;
}

std::string Core::_resolvePath(const char* filename, int path_type) {
	// just return the filename for now
	std::string ret(filename);
	return ret;
}

trss_message* Core::loadFile(const char* filename, int path_type) {
	std::string truepath = _resolvePath(filename, path_type);

	std::streampos size;
	std::ifstream file(truepath.c_str(), std::ios::in|std::ios::binary|std::ios::ate);
	if (file.is_open())
	{
		size = file.tellg();
		trss_message* ret = allocateMessage((int)size);
		file.seekg (0, std::ios::beg);
		file.read ((char*)(ret->data), size);
		file.close();

		return ret;
	} else {
		std::cout << "Unable to open file\n";
		return NULL;
	}
}

void Core::saveFile(const char* filename, int path_type, trss_message* data) {
	std::string truepath = _resolvePath(filename, path_type);

	std::ofstream outfile;
	outfile.open(truepath.c_str(), std::ios::binary | std::ios::out);
	outfile.write((char*)(data->data), data->data_length);
	outfile.close();
}

Core::~Core(){
	// eeeehn
}

Core::Core(){
	_coreLock = SDL_CreateMutex();
}
<commit_msg>no longer segfault if bootstrap.t missing<commit_after>// C++ truss implementation

// TODO: switch to a better logging framework
#include <iostream>
#include <fstream>
#include "trussapi.h"
#include "truss.h"
#include "terra.h"

using namespace trss;

Interpreter::Interpreter(int id, const char* name) {
		_thread = NULL;
		_messageLock = SDL_CreateMutex();
		_execLock = SDL_CreateMutex();
		_terraState = NULL;
		_running = false;
		_autoExecute = true;
		_executeOnMessage = false;
		_executeNext = false;
		_name = name;
		_ID = id;
		_curMessages = new std::vector < trss_message* > ;
		_fetchedMessages = new std::vector < trss_message* >;
}

Interpreter::~Interpreter() {
	// Nothing special to do
}

const std::string& Interpreter::getName() const {
	return _name;
}

int Interpreter::getID() const {
	return _ID;
}

void Interpreter::attachAddon(Addon* addon) {
	if(!_running && _thread == NULL) {
		_addons.push_back(addon);
	} else {
		std::cout << "Cannot attach addon to running interpreter.\n";
		delete addon;
	}
}

int Interpreter::numAddons() {
	return (int)(_addons.size());
}

Addon* Interpreter::getAddon(int idx) {
	if(idx >= 0 && idx < _addons.size()) {
		return _addons[idx];
	} else {
		return NULL;
	}
}

int run_interpreter_thread(void* interpreter) {
	Interpreter* target = (Interpreter*)interpreter;
	target->_threadEntry();
	return 0;
}

void Interpreter::start(const char* arg) {
	if(_thread != NULL || _running) {
		std::cout << "Can't start interpreter twice: already running\n";
		return;
	}

	_running = true;
	_thread = SDL_CreateThread(run_interpreter_thread,
								_name.c_str(),
								(void*)this);
}

void Interpreter::startUnthreaded(const char* arg) {
	if(_thread != NULL || _running) {
		std::cout << "Can't start interpreter twice: already running\n";
		return;
	}

	_running = true;
	_threadEntry();
}

void Interpreter::stop() {
	_running = false;
}

void Interpreter::execute() {
	std::cout << "Interpreter::execute not implemented!\n";
	// TODO: make this do something
}

void Interpreter::_threadEntry() {
	_terraState = luaL_newstate();
	luaL_openlibs(_terraState);
	terra_Options* opts = new terra_Options;
	opts->verbose = 2; // very verbose
	opts->debug = 1; // debug enabled
	terra_initwithoptions(_terraState, opts);
	delete opts; // not sure if necessary or desireable

	// load and execute the bootstrap script
	trss_message* bootstrap = trss_load_file("bootstrap.t", TRSS_CORE_PATH);
	if (!bootstrap) {
		std::cout << "Error loading bootstrap script.\n";
		_running = false;
		return;
	}
	terra_loadbuffer(_terraState,
                     (char*)bootstrap->data,
                     bootstrap->data_length,
                     "bootstrap.t");
	int res = lua_pcall(_terraState, 0, 0, 0);
	if(res != 0) {
		std::cout << "Error bootstrapping interpreter: "
				  << lua_tostring(_terraState, -1) << std::endl;
		_running = false;
		return;
	}

	// Init all the addons
	for(size_t i = 0; i < _addons.size(); ++i) {
		_addons[i]->init(this);
	}

	// Call init
	_safeLuaCall("_core_init");

	double dt = 1.0 / 60.0; // just fudge this at the moment

	// Enter thread main loop
	while(_running) {
		// update addons
		for(unsigned int i = 0; i < _addons.size(); ++i) {
			_addons[i]->update(dt);
		}

		// update lua
		_safeLuaCall("_core_update");
	}

	// Shutdown
	std::cout << "Shuttind down.\n";
	// TODO: actually shutdown stuff here
}

void Interpreter::sendMessage(trss_message* message) {
	SDL_LockMutex(_messageLock);
	trss_acquire_message(message);
	_curMessages->push_back(message);
	SDL_UnlockMutex(_messageLock);
}

int Interpreter::fetchMessages() {
	SDL_LockMutex(_messageLock);
	// swap messages
	std::vector<trss_message*>* temp = _curMessages;
	_curMessages = _fetchedMessages;
	_fetchedMessages = temp;

	// clear the 'current' messages (i.e., the old fetched messages)
	for(unsigned int i = 0; i < _curMessages->size(); ++i) {
		trss_release_message((*_curMessages)[i]);
	}
	_curMessages->clear();
	size_t numMessages = _fetchedMessages->size();

	SDL_UnlockMutex(_messageLock);
	return (int)(numMessages);
}

trss_message* Interpreter::getMessage(int index) {
	// Note: don't need to lock because only 'our' thread
	// should call fetchMessages (which is the only other function
	// that touches _fetchedMessages)
	return (*_fetchedMessages)[index];
}

void Interpreter::_safeLuaCall(const char* funcname, const char* argstr) {
	int nargs = 0;
	lua_getglobal(_terraState, funcname);
	if(argstr != NULL) {
		nargs = 1;
		lua_pushstring(_terraState, argstr);
	}
	int res = lua_pcall(_terraState, nargs, 0, 0);
	if(res != 0) {
		std::cout << lua_tostring(_terraState, -1) << std::endl;
	}
}

void trss_log(int log_level, const char* str){
	Core::getCore()->logMessage(log_level, str);
}

trss_message* trss_load_file(const char* filename, int path_type){
	return Core::getCore()->loadFile(filename, path_type);
}

/* Note that when saving the message_type field is not saved */
int trss_save_file(const char* filename, int path_type, trss_message* data){
	Core::getCore()->saveFile(filename, path_type, data);
	return 0; // TODO: actually check for errors
}

/* Interpreter management functions */
int trss_spawn_interpreter(const char* name){
	Interpreter* spawned = Core::getCore()->spawnInterpreter(name);
	return spawned->getID();
}

void trss_start_interpreter(trss_interpreter_id target_id, const char* msgstr) {
	Core::getCore()->getInterpreter(target_id)->start(msgstr);
}

void trss_stop_interpreter(trss_interpreter_id target_id){
	Core::getCore()->getInterpreter(target_id)->stop();
}

void trss_execute_interpreter(trss_interpreter_id target_id){
	return Core::getCore()->getInterpreter(target_id)->execute();
}

int trss_find_interpreter(const char* name){
	return Core::getCore()->getNamedInterpreter(name)->getID();
}

void trss_send_message(trss_interpreter_id dest, trss_message* message){
	Core::getCore()->dispatchMessage(dest, message);
}

int trss_fetch_messages(trss_interpreter_id idx){
	Interpreter* interpreter = Core::getCore()->getInterpreter(idx);
	if(interpreter) {
		return interpreter->fetchMessages();
	} else {
		return -1;
	}
}

trss_message* trss_get_message(trss_interpreter_id idx, int message_index){
	Interpreter* interpreter = Core::getCore()->getInterpreter(idx);
	if(interpreter) {
		return interpreter->getMessage(message_index);
	} else {
		return NULL;
	}
}

int trss_get_addon_count(trss_interpreter_id target_id) {
	Interpreter* interpreter = Core::getCore()->getInterpreter(target_id);
	if(interpreter) {
		return interpreter->numAddons();
	} else {
		return -1;
	}
}

Addon* trss_get_addon(trss_interpreter_id target_id, int addon_idx) {
	Interpreter* interpreter = Core::getCore()->getInterpreter(target_id);
	if(interpreter) {
		return interpreter->getAddon(addon_idx);
	} else {
		return NULL;
	}
}

const char* trss_get_addon_header(trss_interpreter_id target_id, int addon_idx) {
	Addon* addon = trss_get_addon(target_id, addon_idx);
	if(addon) {
		return addon->getCHeader().c_str();
	} else {
		return "";
	}
}

/* Message management functions */
trss_message* trss_create_message(unsigned int data_length){
	return Core::getCore()->allocateMessage(data_length);
}

void trss_acquire_message(trss_message* msg){
	++(msg->_refcount);
}

void trss_release_message(trss_message* msg){
	--(msg->_refcount);
	if(msg->_refcount <= 0) {
		Core::getCore()->deallocateMessage(msg);
	}
}

trss_message* trss_copy_message(trss_message* src){
	trss_message* newmsg = Core::getCore()->allocateMessage(src->data_length);
	newmsg->message_type = src->message_type;
	memcpy(newmsg->data, src->data, newmsg->data_length);
	return newmsg;
}

Core* core() {
	return Core::getCore();
}

Core* Core::__core = NULL;

Core* Core::getCore() {
	if(__core == NULL) {
		__core = new Core();
	}
	return __core;
}

void Core::logMessage(int log_level, const char* msg) {
	SDL_LockMutex(_coreLock);
	// just dump to standard out for the moment
	std::cout << log_level << "|" << msg << std::endl;
	SDL_UnlockMutex(_coreLock);
}

Interpreter* Core::getInterpreter(int idx){
	Interpreter* ret = NULL;
	SDL_LockMutex(_coreLock);
	if(idx >= 0 && idx < _interpreters.size()) {
		ret = _interpreters[idx];
	}
	SDL_UnlockMutex(_coreLock);
	return ret;
}

Interpreter* Core::getNamedInterpreter(const char* name){
	std::string sname(name);
	Interpreter* ret = NULL;
	SDL_LockMutex(_coreLock);
	for(size_t i = 0; i < _interpreters.size(); ++i) {
		if(_interpreters[i]->getName() == sname) {
			ret = _interpreters[i];
			break;
		}
	}
	SDL_UnlockMutex(_coreLock);
	return ret;
}

Interpreter* Core::spawnInterpreter(const char* name){
	SDL_LockMutex(_coreLock);
	Interpreter* interpreter = new Interpreter((int)(_interpreters.size()), name);
	_interpreters.push_back(interpreter);
	SDL_UnlockMutex(_coreLock);
	return interpreter;
}

int Core::numInterpreters(){
	int ret = 0;
	SDL_LockMutex(_coreLock);
	ret = (int)(_interpreters.size());
	SDL_UnlockMutex(_coreLock);
	return ret;
}

void Core::dispatchMessage(int targetIdx, trss_message* msg){
	Interpreter* interpreter = getInterpreter(targetIdx);
	if(interpreter) {
		interpreter->sendMessage(msg);
	}
}

void Core::acquireMessage(trss_message* msg){
	SDL_LockMutex(_coreLock);
	++(msg->_refcount);
	SDL_UnlockMutex(_coreLock);
}

void Core::releaseMessage(trss_message* msg){
	SDL_LockMutex(_coreLock);
	--(msg->_refcount);
	if(msg->_refcount <= 0) {
		deallocateMessage(msg);
	}
	SDL_UnlockMutex(_coreLock);
}

trss_message* Core::copyMessage(trss_message* src){
	SDL_LockMutex(_coreLock);
	trss_message* newmsg = allocateMessage(src->data_length);
	newmsg->message_type = src->message_type;
	memcpy(newmsg->data, src->data, newmsg->data_length);
	SDL_UnlockMutex(_coreLock);
	return newmsg;
}

trss_message* Core::allocateMessage(int dataLength){
	trss_message* ret = new trss_message;
	ret->data = new unsigned char[dataLength];
	ret->data_length = dataLength;
	ret->_refcount = 1;
	return ret;
}

void Core::deallocateMessage(trss_message* msg){
	delete[] msg->data;
	delete msg;
}

std::string Core::_resolvePath(const char* filename, int path_type) {
	// just return the filename for now
	std::string ret(filename);
	return ret;
}

trss_message* Core::loadFile(const char* filename, int path_type) {
	std::string truepath = _resolvePath(filename, path_type);

	std::streampos size;
	std::ifstream file(truepath.c_str(), std::ios::in|std::ios::binary|std::ios::ate);
	if (file.is_open())
	{
		size = file.tellg();
		trss_message* ret = allocateMessage((int)size);
		file.seekg (0, std::ios::beg);
		file.read ((char*)(ret->data), size);
		file.close();

		return ret;
	} else {
		std::cout << "Unable to open file " << filename << "\n";
		return NULL;
	}
}

void Core::saveFile(const char* filename, int path_type, trss_message* data) {
	std::string truepath = _resolvePath(filename, path_type);

	std::ofstream outfile;
	outfile.open(truepath.c_str(), std::ios::binary | std::ios::out);
	outfile.write((char*)(data->data), data->data_length);
	outfile.close();
}

Core::~Core(){
	// eeeehn
}

Core::Core(){
	_coreLock = SDL_CreateMutex();
}
<|endoftext|>