<commit_before>/*
 * Copyright (C) 2016 deipi.com LLC and contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "field_parser.h"

#define DOUBLEDOTS ':'
#define DOUBLEQUOTE '"'
#define SINGLEQUOTE '\''
#define LEFT_SQUARE_BRACKET '['
#define RIGHT_SQUARE_BRACKET ']'
#define COMMA ','

FieldParser::FieldParser(const std::string& p)
	: fstr(p), isEnd(false),
	  len_field(0), off_field(nullptr),
	  len_fieldot(0), off_fieldot(nullptr),
	  len_value(0), off_value(nullptr),
	  len_double_quote_value(0), off_double_quote_value(nullptr),
	  len_single_quote_value(0), off_single_quote_value(nullptr),
	  isrange(false) { }

void
FieldParser::parse()
{
	auto currentState = FieldParser::State::INIT;
	auto oldState = currentState;
	auto currentSymbol = fstr.data();
	char quote;

	while (true) {
		switch (currentState) {
			case FieldParser::State::INIT:
				switch (*currentSymbol) {
					case '_':
						currentState = FieldParser::State::FIELD;
						off_field = currentSymbol;
						off_fieldot = currentSymbol;
						++len_field;
						++len_fieldot;
						break;
					case LEFT_SQUARE_BRACKET:
						currentState = FieldParser::State::INIT_SQUARE_BRACKET;
						isrange = true;
						break;
					case DOUBLEQUOTE:
						currentState = FieldParser::State::QUOTE;
						quote = DOUBLEQUOTE;
						off_double_quote_value = currentSymbol;
						off_value = currentSymbol + 1;
						++len_double_quote_value;
						++len_value;
						break;
					case SINGLEQUOTE:
						currentState = FieldParser::State::QUOTE;
						quote = SINGLEQUOTE;
						off_single_quote_value = currentSymbol;
						off_value = currentSymbol + 1;
						++len_single_quote_value;
						++len_value;
						break;
					default:
						if (isalnum(*currentSymbol)) {
							currentState = FieldParser::State::FIELD;
							off_field = currentSymbol;
							off_fieldot = currentSymbol;
							++len_field;
							++len_fieldot;
						} else if (isspace(*currentSymbol)) {
							currentState = FieldParser::State::INIT;
						} else {
							throw MSG_FieldParserError("Syntax error in query");
						}
						break;
				}
				break;

			case FieldParser::State::FIELD:
				switch (*currentSymbol) {
					case DOUBLEDOTS:
						currentState = FieldParser::State::STARTVALUE;
						++len_fieldot;
						break;
					case '\0':
						len_value = len_field;
						off_value = off_field;
						len_field = len_fieldot = 0;
						off_field = off_fieldot = nullptr;
						return;
					default:
						if (*currentSymbol != ' ') {
							++len_field;
							++len_fieldot;
						}
						break;
				}
				break;

			case FieldParser::State::STARTVALUE:
				switch (*currentSymbol) {
					case DOUBLEQUOTE:
						currentState = FieldParser::State::QUOTE;
						quote = DOUBLEQUOTE;
						off_double_quote_value = currentSymbol;
						off_value = off_double_quote_value + 1;
						++len_double_quote_value;
						++len_value;
						break;
					case SINGLEQUOTE:
						currentState = FieldParser::State::QUOTE;
						quote = SINGLEQUOTE;
						off_single_quote_value = currentSymbol;
						off_value = off_single_quote_value + 1;
						++len_single_quote_value;
						++len_value;
						break;
					case LEFT_SQUARE_BRACKET:
						currentState = FieldParser::State::INIT_SQUARE_BRACKET;
						isrange = true;
						break;
					default:
						currentState = FieldParser::State::VALUE;
						off_value = currentSymbol;
						++len_value;
						break;
				}

			case FieldParser::State::QUOTE:
				switch (*currentSymbol) {
					case '\\':
						currentState = FieldParser::State::ESCAPE;
						oldState = FieldParser::State::QUOTE;
						++len_value;
						switch (quote) {
							case DOUBLEQUOTE:
								++len_double_quote_value;
								break;
							case SINGLEQUOTE:
								++len_single_quote_value;
								break;
						}
						break;
					case '\0':
						++len_value;
						switch (quote) {
							case DOUBLEQUOTE:
								++len_double_quote_value;
								break;
							case SINGLEQUOTE:
								++len_single_quote_value;
								break;
						}
						break;
					default:
						if (*currentSymbol == quote) {
							currentState = FieldParser::State::END;
							switch (quote) {
								case DOUBLEQUOTE:
									++len_double_quote_value;
									--len_value;	// subtract the last quote count
									break;
								case SINGLEQUOTE:
									++len_single_quote_value;
									--len_value;	// subtract the last quote count
									break;
							}
						} else {
							throw MSG_FieldParserError("Expected symbol: '%c'", quote);
						}
						break;
				}
				break;

			case FieldParser::State::ESCAPE:
				if (*currentSymbol != '\0') {
					currentState = oldState;
					switch(currentState) {
						case FieldParser::State::QUOTE:
							++len_value;
							if (quote == DOUBLEQUOTE) {
								++len_double_quote_value;
							} else if (quote == SINGLEQUOTE) {
								++len_single_quote_value;
							}
							break;
						case FieldParser::State::QUOTE_SQUARE_BRACKET:
							if (isEnd) {
								end += *currentSymbol;
							} else {
								start += *currentSymbol;
							}
							break;
						default:
							break;
					}
				} else {
					throw MSG_FieldParserError("Syntax error in query escaped");
				}
				break;

			case FieldParser::State::VALUE:
				if (*currentSymbol == '\0') {
					currentState = FieldParser::State::END;
				} else if (!isspace(*currentSymbol)) {
					++len_value;
				} else {
					throw MSG_FieldParserError("Syntax error in query");
				}
				break;

			case FieldParser::State::INIT_SQUARE_BRACKET:
				switch (*currentSymbol) {
					case DOUBLEQUOTE:
						currentState = FieldParser::State::QUOTE_SQUARE_BRACKET;
						quote = DOUBLEQUOTE;
						break;
					case SINGLEQUOTE:
						currentState = FieldParser::State::QUOTE_SQUARE_BRACKET;
						quote = SINGLEQUOTE;
						break;
					case COMMA:
						currentState = FieldParser::State::SQUARE_BRACKET;
						isEnd = true;
						break;
					case RIGHT_SQUARE_BRACKET:
						currentState = FieldParser::State::END;
						break;
					case '\0':
						start += *currentSymbol;
						break;
					default:
						throw MSG_FieldParserError("Syntax error in query");
				}
				break;

			case FieldParser::State::SQUARE_BRACKET:
				switch (*currentSymbol) {
					case DOUBLEQUOTE:
						currentState = FieldParser::State::QUOTE_SQUARE_BRACKET;
						quote = DOUBLEQUOTE;
						break;
					case SINGLEQUOTE:
						currentState = FieldParser::State::QUOTE_SQUARE_BRACKET;
						quote = SINGLEQUOTE;
						break;
					case RIGHT_SQUARE_BRACKET:
						currentState = FieldParser::State::END;
						break;
					case '\0':
						end += *currentSymbol;
						break;
					default:
						throw MSG_FieldParserError("Expected symbol: ']'");
				}
				break;

			case FieldParser::State::QUOTE_SQUARE_BRACKET:
				switch (*currentSymbol) {
					case '\\':
						currentState = FieldParser::State::ESCAPE;
						oldState = FieldParser::State::QUOTE_SQUARE_BRACKET;
						break;
					case '\0':
						break;
					default:
						if (*currentSymbol == quote) {
							currentState = FieldParser::State::END_SQUARE_BRACKET;
						} else if (isEnd) {
							end += *currentSymbol;
						} else {
							start += *currentSymbol;
						}
						break;
				}
				break;

			case FieldParser::State::END_SQUARE_BRACKET:
				if (*currentSymbol == RIGHT_SQUARE_BRACKET) {
					currentState = FieldParser::State::END;
				} else {
					throw MSG_FieldParserError("Expected symbol: ']'");
				}
				break;

			case FieldParser::State::END: {
				return;
			}
		}

		++currentSymbol;
	}
}
<commit_msg>Fixing Bug in FieldParser<commit_after>/*
 * Copyright (C) 2016 deipi.com LLC and contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "field_parser.h"

#define DOUBLEDOTS ':'
#define DOUBLEQUOTE '"'
#define SINGLEQUOTE '\''
#define LEFT_SQUARE_BRACKET '['
#define RIGHT_SQUARE_BRACKET ']'
#define COMMA ','

FieldParser::FieldParser(const std::string& p)
	: fstr(p), isEnd(false),
	  len_field(0), off_field(nullptr),
	  len_fieldot(0), off_fieldot(nullptr),
	  len_value(0), off_value(nullptr),
	  len_double_quote_value(0), off_double_quote_value(nullptr),
	  len_single_quote_value(0), off_single_quote_value(nullptr),
	  isrange(false) { }

void
FieldParser::parse()
{
	auto currentState = FieldParser::State::INIT;
	auto oldState = currentState;
	auto currentSymbol = fstr.data();
	char quote;

	while (true) {
		switch (currentState) {
			case FieldParser::State::INIT:
				switch (*currentSymbol) {
					case '_':
						currentState = FieldParser::State::FIELD;
						off_field = currentSymbol;
						off_fieldot = currentSymbol;
						++len_field;
						++len_fieldot;
						break;
					case LEFT_SQUARE_BRACKET:
						currentState = FieldParser::State::INIT_SQUARE_BRACKET;
						isrange = true;
						break;
					case DOUBLEQUOTE:
						currentState = FieldParser::State::QUOTE;
						quote = DOUBLEQUOTE;
						off_double_quote_value = currentSymbol;
						off_value = currentSymbol + 1;
						++len_double_quote_value;
						++len_value;
						break;
					case SINGLEQUOTE:
						currentState = FieldParser::State::QUOTE;
						quote = SINGLEQUOTE;
						off_single_quote_value = currentSymbol;
						off_value = currentSymbol + 1;
						++len_single_quote_value;
						++len_value;
						break;
					default:
						if (isalnum(*currentSymbol)) {
							currentState = FieldParser::State::FIELD;
							off_field = currentSymbol;
							off_fieldot = currentSymbol;
							++len_field;
							++len_fieldot;
						} else if (isspace(*currentSymbol)) {
							currentState = FieldParser::State::INIT;
						} else {
							throw MSG_FieldParserError("Syntax error in query");
						}
						break;
				}
				break;

			case FieldParser::State::FIELD:
				switch (*currentSymbol) {
					case DOUBLEDOTS:
						currentState = FieldParser::State::STARTVALUE;
						++len_fieldot;
						break;
					case '\0':
						len_value = len_field;
						off_value = off_field;
						len_field = len_fieldot = 0;
						off_field = off_fieldot = nullptr;
						return;
					default:
						if (*currentSymbol != ' ') {
							++len_field;
							++len_fieldot;
						}
						break;
				}
				break;

			case FieldParser::State::STARTVALUE:
				switch (*currentSymbol) {
					case DOUBLEQUOTE:
						currentState = FieldParser::State::QUOTE;
						quote = DOUBLEQUOTE;
						off_double_quote_value = currentSymbol;
						off_value = off_double_quote_value + 1;
						++len_double_quote_value;
						++len_value;
						break;
					case SINGLEQUOTE:
						currentState = FieldParser::State::QUOTE;
						quote = SINGLEQUOTE;
						off_single_quote_value = currentSymbol;
						off_value = off_single_quote_value + 1;
						++len_single_quote_value;
						++len_value;
						break;
					case LEFT_SQUARE_BRACKET:
						currentState = FieldParser::State::INIT_SQUARE_BRACKET;
						isrange = true;
						break;
					default:
						currentState = FieldParser::State::VALUE;
						off_value = currentSymbol;
						++len_value;
						break;
				}
				break;

			case FieldParser::State::QUOTE:
				switch (*currentSymbol) {
					case '\\':
						currentState = FieldParser::State::ESCAPE;
						oldState = FieldParser::State::QUOTE;
						++len_value;
						switch (quote) {
							case DOUBLEQUOTE:
								++len_double_quote_value;
								break;
							case SINGLEQUOTE:
								++len_single_quote_value;
								break;
						}
						break;
					case '\0':
						++len_value;
						switch (quote) {
							case DOUBLEQUOTE:
								++len_double_quote_value;
								break;
							case SINGLEQUOTE:
								++len_single_quote_value;
								break;
						}
						break;
					default:
						if (*currentSymbol == quote) {
							currentState = FieldParser::State::END;
							switch (quote) {
								case DOUBLEQUOTE:
									++len_double_quote_value;
									--len_value;	// subtract the last quote count
									break;
								case SINGLEQUOTE:
									++len_single_quote_value;
									--len_value;	// subtract the last quote count
									break;
							}
						} else {
							throw MSG_FieldParserError("Expected symbol: '%c'", quote);
						}
						break;
				}
				break;

			case FieldParser::State::ESCAPE:
				if (*currentSymbol != '\0') {
					currentState = oldState;
					switch(currentState) {
						case FieldParser::State::QUOTE:
							++len_value;
							if (quote == DOUBLEQUOTE) {
								++len_double_quote_value;
							} else if (quote == SINGLEQUOTE) {
								++len_single_quote_value;
							}
							break;
						case FieldParser::State::QUOTE_SQUARE_BRACKET:
							if (isEnd) {
								end += *currentSymbol;
							} else {
								start += *currentSymbol;
							}
							break;
						default:
							break;
					}
				} else {
					throw MSG_FieldParserError("Syntax error in query escaped");
				}
				break;

			case FieldParser::State::VALUE:
				if (*currentSymbol == '\0') {
					currentState = FieldParser::State::END;
				} else if (!isspace(*currentSymbol)) {
					++len_value;
				} else {
					throw MSG_FieldParserError("Syntax error in query");
				}
				break;

			case FieldParser::State::INIT_SQUARE_BRACKET:
				switch (*currentSymbol) {
					case DOUBLEQUOTE:
						currentState = FieldParser::State::QUOTE_SQUARE_BRACKET;
						quote = DOUBLEQUOTE;
						break;
					case SINGLEQUOTE:
						currentState = FieldParser::State::QUOTE_SQUARE_BRACKET;
						quote = SINGLEQUOTE;
						break;
					case COMMA:
						currentState = FieldParser::State::SQUARE_BRACKET;
						isEnd = true;
						break;
					case RIGHT_SQUARE_BRACKET:
						currentState = FieldParser::State::END;
						break;
					case '\0':
						start += *currentSymbol;
						break;
					default:
						throw MSG_FieldParserError("Syntax error in query");
				}
				break;

			case FieldParser::State::SQUARE_BRACKET:
				switch (*currentSymbol) {
					case DOUBLEQUOTE:
						currentState = FieldParser::State::QUOTE_SQUARE_BRACKET;
						quote = DOUBLEQUOTE;
						break;
					case SINGLEQUOTE:
						currentState = FieldParser::State::QUOTE_SQUARE_BRACKET;
						quote = SINGLEQUOTE;
						break;
					case RIGHT_SQUARE_BRACKET:
						currentState = FieldParser::State::END;
						break;
					case '\0':
						end += *currentSymbol;
						break;
					default:
						throw MSG_FieldParserError("Expected symbol: ']'");
				}
				break;

			case FieldParser::State::QUOTE_SQUARE_BRACKET:
				switch (*currentSymbol) {
					case '\\':
						currentState = FieldParser::State::ESCAPE;
						oldState = FieldParser::State::QUOTE_SQUARE_BRACKET;
						break;
					case '\0':
						break;
					default:
						if (*currentSymbol == quote) {
							currentState = FieldParser::State::END_SQUARE_BRACKET;
						} else if (isEnd) {
							end += *currentSymbol;
						} else {
							start += *currentSymbol;
						}
						break;
				}
				break;

			case FieldParser::State::END_SQUARE_BRACKET:
				if (*currentSymbol == RIGHT_SQUARE_BRACKET) {
					currentState = FieldParser::State::END;
				} else {
					throw MSG_FieldParserError("Expected symbol: ']'");
				}
				break;

			case FieldParser::State::END: {
				return;
			}
		}

		++currentSymbol;
	}
}
<|endoftext|>


<commit_before>/*
* Copyright (c)2015 - 2016 Oasis LMF Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*
*   * Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in
*     the documentation and/or other materials provided with the
*     distribution.
*
*   * Neither the original author of this software nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
/*
Author: Ben Matharu  email: ben.matharu@oasislmf.org
*/
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <fcntl.h>
#include <assert.h>
#include "fmcalc.h"
#include "../include/oasis.h"

#if defined(_MSC_VER)
#include "../wingetopt/wingetopt.h"
#else
#include <unistd.h>
#include <signal.h>
#include <string.h>
#endif

char *progname = 0;

void help()
{

    fprintf(stderr,
		"-a set allocrule (default none)\n"
		"-o run old fm_profile\n"
        "-M max level (optional)\n"
		"-p inputpath (relative or full path)\n"
		"-n feed net value (used for reinsurance)\n"
		"-O Alloc rule2 optimization off"
		"-d debug\n"
		"-v version\n"
		"-h help\n"
	);
}

#if !defined(_MSC_VER) && !defined(__MINGW32__)
void segfault_sigaction(int signal, siginfo_t *si, void *arg)
{
	fprintf(stderr, "%s: Segment fault at address: %p\n", progname, si->si_addr);
	exit(0);
}
#endif

int main(int argc, char* argv[])
{
	progname = argv[0];
    int new_max = -1;
	int allocrule = 0;
	int opt;
	std::string inputpath;
	bool oldFMProfile = false;
	bool debug = false;
	bool allocruleOptimizationOff = false;

	bool netvalue = false;
    while ((opt = getopt(argc, argv, "dnvhoOM:p:a:")) != -1) {
        switch (opt) {
		case 'o':
			oldFMProfile = true;
			break;
		case 'O':
			allocruleOptimizationOff = true;
			break;
		case 'd':
			debug = true;
			break;
         case 'M':
            new_max = atoi(optarg);
            break;
		 case 'a':
			 allocrule = atoi(optarg);
			 break;
		 case 'v':
			 fprintf(stderr, "%s : version: %s\n", argv[0], VERSION);
			 exit(EXIT_FAILURE);
			 break;
		 case 'p':
			 inputpath = optarg;
			 break;
		 case 'n':
			 netvalue = true;
			 break;
        case 'h':
           help();
           exit(EXIT_FAILURE);
        default:
            help();
            exit(EXIT_FAILURE);
        }
    }

#if !defined(_MSC_VER) && !defined(__MINGW32__)
	struct sigaction sa;

	memset(&sa, 0, sizeof(struct sigaction));
	sigemptyset(&sa.sa_mask);
	sa.sa_sigaction = segfault_sigaction;
	sa.sa_flags = SA_SIGINFO;

	sigaction(SIGSEGV, &sa, NULL);
#endif
	if (allocrule < 0 || allocrule > 2) {
		fprintf(stderr, "%s: Invalid allocrule %d\n", progname,allocrule);
		exit(1);
	}

	try {
		initstreams("", "");
		fmcalc fc(new_max, allocrule, inputpath, netvalue, oldFMProfile,debug, allocruleOptimizationOff);
		fc.doit();
	}
	catch (std::bad_alloc) {
		fprintf(stderr, "%s: Memory allocation failed\n", progname);
		exit(0);
	}

	return 0;
}
<commit_msg>Fix return code on fmcalc<commit_after>/*
* Copyright (c)2015 - 2016 Oasis LMF Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*
*   * Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in
*     the documentation and/or other materials provided with the
*     distribution.
*
*   * Neither the original author of this software nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
/*
Author: Ben Matharu  email: ben.matharu@oasislmf.org
*/
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <fcntl.h>
#include <assert.h>
#include "fmcalc.h"
#include "../include/oasis.h"

#if defined(_MSC_VER)
#include "../wingetopt/wingetopt.h"
#else
#include <unistd.h>
#include <signal.h>
#include <string.h>
#endif

char *progname = 0;

void help()
{

    fprintf(stderr,
		"-a set allocrule (default none)\n"
		"-o run old fm_profile\n"
        "-M max level (optional)\n"
		"-p inputpath (relative or full path)\n"
		"-n feed net value (used for reinsurance)\n"
		"-O Alloc rule2 optimization off"
		"-d debug\n"
		"-v version\n"
		"-h help\n"
	);
}

#if !defined(_MSC_VER) && !defined(__MINGW32__)
void segfault_sigaction(int signal, siginfo_t *si, void *arg)
{
	fprintf(stderr, "%s: Segment fault at address: %p\n", progname, si->si_addr);
	exit(0);
}
#endif

int main(int argc, char* argv[])
{
	progname = argv[0];
    int new_max = -1;
	int allocrule = 0;
	int opt;
	std::string inputpath;
	bool oldFMProfile = false;
	bool debug = false;
	bool allocruleOptimizationOff = false;

	bool netvalue = false;
    while ((opt = getopt(argc, argv, "dnvhoOM:p:a:")) != -1) {
        switch (opt) {
		case 'o':
			oldFMProfile = true;
			break;
		case 'O':
			allocruleOptimizationOff = true;
			break;
		case 'd':
			debug = true;
			break;
         case 'M':
            new_max = atoi(optarg);
            break;
		 case 'a':
			 allocrule = atoi(optarg);
			 break;
		 case 'v':
			 fprintf(stderr, "%s : version: %s\n", argv[0], VERSION);
			 exit(EXIT_FAILURE);
			 break;
		 case 'p':
			 inputpath = optarg;
			 break;
		 case 'n':
			 netvalue = true;
			 break;
        case 'h':
           help();
           exit(EXIT_FAILURE);
        default:
            help();
            exit(EXIT_FAILURE);
        }
    }

#if !defined(_MSC_VER) && !defined(__MINGW32__)
	struct sigaction sa;

	memset(&sa, 0, sizeof(struct sigaction));
	sigemptyset(&sa.sa_mask);
	sa.sa_sigaction = segfault_sigaction;
	sa.sa_flags = SA_SIGINFO;

	sigaction(SIGSEGV, &sa, NULL);
#endif
	if (allocrule < 0 || allocrule > 2) {
		fprintf(stderr, "%s: Invalid allocrule %d\n", progname,allocrule);
		exit(1);
	}

	try {
		initstreams("", "");
		fmcalc fc(new_max, allocrule, inputpath, netvalue, oldFMProfile,debug, allocruleOptimizationOff);
		fc.doit();
	}
	catch (std::bad_alloc) {
		fprintf(stderr, "%s: Memory allocation failed\n", progname);
		exit(1);
	}

	return 0;
}
<|endoftext|>


<commit_before>#include "likelihood.h"

#include <queso/GslVector.h>
#include <queso/GslMatrix.h>
#include <queso/VectorSet.h>

#include <mkl.h>

#include <cmath>

template <class V, class M>
Likelihood<V, M>::Likelihood(const char * prefix,
    const QUESO::VectorSet<V, M> & domainSet)
  : QUESO::BaseScalarFunction<V, M>(prefix, domainSet),
    m_observationParameter(1.0),
    m_num_simulations(10),
    m_simulations(m_num_simulations),
    m_simulationParameters(m_num_simulations),
    m_rho(0.5)
{
  // Generate observational data
  double x = 0.25;  // Observation location
  m_observation = m_observationParameter * std::sin(2.0 * M_PI * x);

  // Generate `simulation data'
  for (unsigned int i = 0; i < m_num_simulations; i++) {
    // Evenly spaced parameters between 0 and 2
    m_simulationParameters[i] = i * 2.0 / (m_num_simulations - 1);
    // Observable is at the same location as the experiment
    m_simulations[i] = m_simulationParameters[i] * std::sin(2.0 * M_PI * x);
  }

  // Allocate memory for the covariance matrix
  // Exceptions will lead to memory leaks.  lul
  m_covariance = (double *)malloc(sizeof(double) *
                                  (m_num_simulations + 1) *
                                  (m_num_simulations + 1));

  if (m_covariance == NULL) {
    queso_error_msg("Could not allocate memory for covariance matrix");
  }
}

template <class V, class M>
Likelihood<V, M>::~Likelihood()
{
  free(m_covariance);
}

template <class V, class M>
double
Likelihood<V, M>::lnValue(const V & domainVector, const V * domainDirection,
    V * gradVector, M * hessianMatrix, V * hessianEffect) const
{
  unsigned int total_dim = m_num_simulations + 1;  // Plus 1 for one experiment

  // First, fill up the covariance matrix
  for (unsigned int i = 0; i < total_dim; i++) {
    double parameter1;
    // Deal with the single experiment
    if (i == 0) {
      // Difference in scenario variables is always zero.  No need to handle it.
      // Deal with difference in parameters
      parameter1 = domainVector[0];
    }
    else {
      // Subtract 1 because we have 1 experiment (observation)
      parameter1 = m_simulationParameters[i-1];
    }

    for (unsigned int j = 0; j < total_dim; j++) {
      double parameter2;

      // Deal with the single experiment (observation)
      if (j == 0) {
        parameter2 = domainVector[0];
      }
      else {
        // Subtract 1 because we have 1 experiment (observation)
        parameter2 = m_simulationParameters[j-1];
      }

      double param_diff = parameter1 - parameter2;
      m_covariance[i*total_dim+j] = std::pow(m_rho, 4.0 * param_diff * param_diff);
    }
  }

  // We're letting MKL choose the workspace array at runtime
  // Assume unsigned int N converts to lapack_int
  int info = LAPACKE_dpotrf(LAPACK_ROW_MAJOR, 'U', total_dim, m_covariance, total_dim);

  std::cout << "LAPACKE_dpotrf return value is: " << info << std::endl;

  return 0;
}

template <class V, class M>
double
Likelihood<V, M>::actualValue(const V & domainVector,
    const V * domainDirection, V * gradVector, M * hessianMatrix,
    V * hessianEffect) const
{
  return std::exp(this->lnValue(domainVector,
                                domainDirection,
                                gradVector,
                                hessianMatrix,
                                hessianEffect));
}

template class Likelihood<QUESO::GslVector, QUESO::GslMatrix>;
<commit_msg>Adding rest of likelihood implementation<commit_after>#include "likelihood.h"

#include <queso/GslVector.h>
#include <queso/GslMatrix.h>
#include <queso/VectorSet.h>

#include <mkl.h>

#include <cmath>

template <class V, class M>
Likelihood<V, M>::Likelihood(const char * prefix,
    const QUESO::VectorSet<V, M> & domainSet)
  : QUESO::BaseScalarFunction<V, M>(prefix, domainSet),
    m_observationParameter(1.0),
    m_num_simulations(10),
    m_simulations(m_num_simulations),
    m_simulationParameters(m_num_simulations),
    m_rho(0.5)
{
  // Generate observational data
  double x = 0.25;  // Observation location
  m_observation = m_observationParameter * std::sin(2.0 * M_PI * x);

  // Generate `simulation data'
  for (unsigned int i = 0; i < m_num_simulations; i++) {
    // Evenly spaced parameters between 0 and 2
    m_simulationParameters[i] = i * 2.0 / (m_num_simulations - 1);
    // Observable is at the same location as the experiment
    m_simulations[i] = m_simulationParameters[i] * std::sin(2.0 * M_PI * x);
  }

  // Allocate memory for the covariance matrix
  // Exceptions will lead to memory leaks.  lul
  m_covariance = (double *)malloc(sizeof(double) *
                                  (m_num_simulations + 1) *
                                  (m_num_simulations + 1));

  if (m_covariance == NULL) {
    queso_error_msg("Could not allocate memory for covariance matrix");
  }
}

template <class V, class M>
Likelihood<V, M>::~Likelihood()
{
  free(m_covariance);
}

template <class V, class M>
double
Likelihood<V, M>::lnValue(const V & domainVector, const V * domainDirection,
    V * gradVector, M * hessianMatrix, V * hessianEffect) const
{
  unsigned int total_dim = m_num_simulations + 1;  // Plus 1 for one experiment

  // First, fill up the covariance matrix
  for (unsigned int i = 0; i < total_dim; i++) {
    double parameter1;
    // Deal with the single experiment
    if (i == 0) {
      // Difference in scenario variables is always zero.  No need to handle it.
      // Deal with difference in parameters
      parameter1 = domainVector[0];
    }
    else {
      // Subtract 1 because we have 1 experiment (observation)
      parameter1 = m_simulationParameters[i-1];
    }

    for (unsigned int j = 0; j < total_dim; j++) {
      double parameter2;

      // Deal with the single experiment (observation)
      if (j == 0) {
        parameter2 = domainVector[0];
      }
      else {
        // Subtract 1 because we have 1 experiment (observation)
        parameter2 = m_simulationParameters[j-1];
      }

      double param_diff = parameter1 - parameter2;
      m_covariance[i*total_dim+j] = std::pow(m_rho, 4.0 * param_diff * param_diff);
    }
  }

  int info;
  // We're letting MKL choose the workspace array at runtime
  // Assume unsigned int N converts to lapack_int
  info = LAPACKE_dpotrf(LAPACK_ROW_MAJOR, 'U', total_dim, m_covariance, total_dim);

  if (info == 0) {
    std::cout << "LAPACKE_dpotrf was successful" << std::endl;
  }
  else if (info < 0) {
    std::cout << "LAPACKE_dpotrf was unsuccessful."
              << "  Parameter " << info << " had an illegal value."
              << std::endl;
  }
  else {  // if (info > 0) {
    std::cout << "LAPACKE_dpotrf was unseccessful."
              << "  The leading minor of order " << info << " is not pos. def."
              << "  The Cholesky factorisation could not be completed."
              << std::endl;
  }

  // Compute the \infty-norm of m_covariance
  // All elements of m_covariance are nonnegative
  double norm = 0.0;
  for (unsigned int i = 0; i < total_dim; i++) {
    double tmp = 0.0;

    for (unsigned int j = 0; j < total_dim; j++) {
      tmp += m_covariance[i*total_dim+j];
    }

    if (tmp > norm) {
      norm = tmp;
    }
  }

  // Estimate the condition number of m_covariance
  double cond;
  info = LAPACKE_dpocon(LAPACK_ROW_MAJOR, 'U', total_dim, m_covariance, total_dim, norm, &cond);

  if (info == 0) {
    std::cout << "Approximate reciprocal condition number of m_covariance is: " << cond << std::endl;
  }
  else {
    std::cout << "Condition number estimation failed."
              << "  Parameter " << info << " had an illegal value."
              << std::endl;
  }

  // Now do y^T \Sigma^{-1} y
  // First solve \Sigma x = y for x
  double * y = (double *)malloc(sizeof(double) * total_dim);
  double * x = (double *)malloc(sizeof(double) * total_dim);
  y[0] = m_observation;
  x[0] = m_observation;
  for (unsigned int i = 0; i < m_num_simulations; i++) {
    y[i+1] = m_simulations[i];
    x[i+1] = m_simulations[i];
  }

  info = LAPACKE_dpotrs(LAPACK_ROW_MAJOR, 'U', total_dim, 1, m_covariance, total_dim, x, total_dim);
  if (info == 0) {
    std::cout << "LAPACKE_dpotrs successful" << std::endl;
  }
  else {
    std::cout << "LAPACKE_dpotrs unsuccessful.  Parameter " << info << " had an illegal value" << std::endl;
  }

  // Second compute y^T x
  double llhd = cblas_ddot(total_dim, y, 1, x, 1);

  return -0.5 * llhd;
}

template <class V, class M>
double
Likelihood<V, M>::actualValue(const V & domainVector,
    const V * domainDirection, V * gradVector, M * hessianMatrix,
    V * hessianEffect) const
{
  return std::exp(this->lnValue(domainVector,
                                domainDirection,
                                gradVector,
                                hessianMatrix,
                                hessianEffect));
}

template class Likelihood<QUESO::GslVector, QUESO::GslMatrix>;
<|endoftext|>


<commit_before><commit_msg>gui: display location with correct precision<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2002-2007 Novamente LLC
 * Copyright (C) 2008 by Singularity Institute for Artificial Intelligence
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/util/platform.h>
#include "../../PLN.h"

#include "../Rule.h"
#include "../Rules.h"
#include "../../AtomSpaceWrapper.h"
#include "../../PLNatom.h"
#include "../../BackInferenceTreeNode.h"

namespace opencog { namespace pln {

StrictImplicationBreakdownRule::StrictImplicationBreakdownRule(AtomSpaceWrapper *_asw)
  : Rule(_asw,false,true,"ModusPonensRule")
{
    inputFilter.push_back(meta(
                               new tree<Vertex>(
                                                mva((pHandle)IMPLICATION_LINK,
                                                    mva((pHandle)ATOM),
                                                    mva((pHandle)ATOM)))
                               ));
    inputFilter.push_back(meta(
                               new tree<Vertex>(
                                                mva((pHandle)ATOM))
                               ));
}

// Won't work since Rule::o2iMeta requires a target to have children
// (and removing that restriction breaks other things).
//meta StrictImplicationBreakdownRule::targetTemplate() const
//{
//    return(meta(new vtree(mva((pHandle)ATOM))));
//}

Rule::setOfMPs StrictImplicationBreakdownRule::fullInputFilter() const
{
	//meta outh(new vtree(mva((pHandle)ATOM)));

    MPs ret;
    Vertex myvar = CreateVar(asw);

    // It is necessary to use an FWVar rather than ATOM so that CCURule will match it.
    meta outh(new vtree(CreateVar(asw)));

    cprintf(4,"\n\nTo produce\n");
    NMPrinter printer(NMP_HANDLE|NMP_TYPE_NAME);
    printer.print(outh->begin(), 4);

    ret.push_back(BBvtree(new BoundVTree(mva((pHandle)IMPLICATION_LINK,
                                             vtree(myvar),*outh))));
    cprintf(4,"Need:\n");
    ret.push_back(BBvtree(new BoundVTree(myvar)));
    printer.print(ret[0]->begin(), 4);
    printer.print(ret[1]->begin(), 4);

    cprintf(4,"-----\n");

    return makeSingletonSet(ret);
}

Rule::setOfMPs StrictImplicationBreakdownRule::o2iMetaExtra(meta outh, bool& overrideInputFilter) const
{
    ///haxx:: (restricts internal implications

    //      if (asw->isSubType(v2h(*outh->begin()), IMPLICATION_LINK))
    //          return Rule::setOfMPs();

    MPs ret;
    Vertex myvar = CreateVar(asw);

    cprintf(4,"\n\nTo produce\n");
    NMPrinter printer(NMP_HANDLE|NMP_TYPE_NAME);
    printer.print(outh->begin(), 4);

    ret.push_back(BBvtree(new BoundVTree(mva((pHandle)IMPLICATION_LINK,
                                             vtree(myvar),*outh))));
    cprintf(4,"Need:\n");
    ret.push_back(BBvtree(new BoundVTree(myvar)));
    printer.print(ret[0]->begin(), 4);
    printer.print(ret[1]->begin(), 4);

    cprintf(4,"-----\n");

    overrideInputFilter = true;

    return makeSingletonSet(ret);
}

BoundVertex StrictImplicationBreakdownRule::compute(const std::vector<Vertex>& premiseArray, pHandle CX, bool fresh) const
{
    assert(validate(premiseArray));

    //printTree(premiseArray[0],0,1);

    cprintf(3,"StrictImplicationBreakdownRule::compute:");

    NMPrinter printer(NMP_ALL);
    for (uint i=0;i<premiseArray.size();i++)
        printer.print(_v2h(premiseArray[i]), 3);

    //vtree   vt1(make_vtree(_v2h(premiseArray[0]))),
    //    vt2(make_vtree(_v2h(premiseArray[1])));

    /** haxx:: \todo Temporarily disabled!
        This check does not hold if one of the args
        has been executed but the other one has not.
        Execution here means that Eval(!now) becomes Eval(35353).
        ! is a hacky shorthand for grounded predicates for now.

        The real solution will be tointroduce an equality check which considers
        the unexecuted and executed forms equal.
    */

#if 0

    if (make_vtree(asw->getOutgoing(v2h(premiseArray[0]),0))
        != make_vtree(v2h(premiseArray[1])))
        {
            cprintf(0,"StrictImplicationBreakdownRule args fail:\n");
#if 0
            printTree(v2h(premiseArray[0]),0,0);
            printTree(asw->getOutgoing(v2h(premiseArray[0]),0),0,0);
            printTree(v2h(premiseArray[1]),0,0);

            //      rawPrint(premiseArray[0], premiseArray[0].begin(), 0);
            rawPrint(vt1, vt1.begin(), 0);
            rawPrint(vt2, vt2.begin(), 0);
#else
            printer.print(v2h(premiseArray[0]), -10);
            printer.print(asw->getOutgoing(v2h(premiseArray[0]),0), -10);
            printer.print(v2h(premiseArray[1]), -10);

            //        printer.print(premiseArray[0].begin());
            printer.print(vt1.begin(), -10);
            printer.print(vt2.begin(), -10);
#endif
            assert(0);
        }
#endif

    pHandle implication = _v2h(premiseArray[0]);
    pHandle antecedant = _v2h(premiseArray[1]);
    pHandle conclusion = asw->getOutgoing(implication, 1);

    TruthValue* tvs[] = {
        (TruthValue*) &(asw->getTV(implication)),
        (TruthValue*) &(asw->getTV(antecedant)),
        (TruthValue*) &(asw->getTV(conclusion))
        };

    TruthValue* retTV =
        ImplicationBreakdownFormula().compute(tvs, 3);

    // update the TV of the conclusion.
    // Note that ret is different than conclusion, that is because a dummy
    // context is added and this is translated into a different resulting
    // pHandle (but of course they both correspond to the same atom).
    // See AtomSpaceWrapper.h for more info
    pHandle ret = asw->updateTV(conclusion, *retTV, fresh);

    delete retTV;

    printer.print(ret, 3);

    return Vertex(ret);
}

}} // namespace opencog { namespace pln {
<commit_msg>PLN inference control: Disable support for nested implications, because it isn't used and slows things down.<commit_after>/*
 * Copyright (C) 2002-2007 Novamente LLC
 * Copyright (C) 2008 by Singularity Institute for Artificial Intelligence
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/util/platform.h>
#include "../../PLN.h"

#include "../Rule.h"
#include "../Rules.h"
#include "../../AtomSpaceWrapper.h"
#include "../../PLNatom.h"
#include "../../BackInferenceTreeNode.h"

namespace opencog { namespace pln {

StrictImplicationBreakdownRule::StrictImplicationBreakdownRule(AtomSpaceWrapper *_asw)
  : Rule(_asw,false,true,"ModusPonensRule")
{
    inputFilter.push_back(meta(
                               new tree<Vertex>(
                                                mva((pHandle)IMPLICATION_LINK,
                                                    mva((pHandle)ATOM),
                                                    mva((pHandle)ATOM)))
                               ));
    inputFilter.push_back(meta(
                               new tree<Vertex>(
                                                mva((pHandle)ATOM))
                               ));
}

// Won't work since Rule::o2iMeta requires a target to have children
// (and removing that restriction breaks other things).
//meta StrictImplicationBreakdownRule::targetTemplate() const
//{
//    return(meta(new vtree(mva((pHandle)ATOM))));
//}

Rule::setOfMPs StrictImplicationBreakdownRule::fullInputFilter() const
{
	//meta outh(new vtree(mva((pHandle)ATOM)));

    MPs ret;
    Vertex myvar = CreateVar(asw);

    // It is necessary to use an FWVar rather than ATOM so that CCURule will match it.
    meta outh(new vtree(CreateVar(asw)));

    cprintf(4,"\n\nTo produce\n");
    NMPrinter printer(NMP_HANDLE|NMP_TYPE_NAME);
    printer.print(outh->begin(), 4);

    ret.push_back(BBvtree(new BoundVTree(mva((pHandle)IMPLICATION_LINK,
                                             vtree(myvar),*outh))));
    cprintf(4,"Need:\n");
    ret.push_back(BBvtree(new BoundVTree(myvar)));
    printer.print(ret[0]->begin(), 4);
    printer.print(ret[1]->begin(), 4);

    cprintf(4,"-----\n");

    return makeSingletonSet(ret);
}

Rule::setOfMPs StrictImplicationBreakdownRule::o2iMetaExtra(meta outh, bool& overrideInputFilter) const
{
    ///haxx:: (restricts internal implications
    // - Leave it on for now, because it is not necessary (currently) and it makes
    // everything faster.

    if (asw->isSubType(_v2h(*outh->begin()), IMPLICATION_LINK))
        return Rule::setOfMPs();

    MPs ret;
    Vertex myvar = CreateVar(asw);

    cprintf(4,"\n\nTo produce\n");
    NMPrinter printer(NMP_HANDLE|NMP_TYPE_NAME);
    printer.print(outh->begin(), 4);

    ret.push_back(BBvtree(new BoundVTree(mva((pHandle)IMPLICATION_LINK,
                                             vtree(myvar),*outh))));
    cprintf(4,"Need:\n");
    ret.push_back(BBvtree(new BoundVTree(myvar)));
    printer.print(ret[0]->begin(), 4);
    printer.print(ret[1]->begin(), 4);

    cprintf(4,"-----\n");

    overrideInputFilter = true;

    return makeSingletonSet(ret);
}

BoundVertex StrictImplicationBreakdownRule::compute(const std::vector<Vertex>& premiseArray, pHandle CX, bool fresh) const
{
    assert(validate(premiseArray));

    //printTree(premiseArray[0],0,1);

    cprintf(3,"StrictImplicationBreakdownRule::compute:");

    NMPrinter printer(NMP_ALL);
    for (uint i=0;i<premiseArray.size();i++)
        printer.print(_v2h(premiseArray[i]), 3);

    //vtree   vt1(make_vtree(_v2h(premiseArray[0]))),
    //    vt2(make_vtree(_v2h(premiseArray[1])));

    /** haxx:: \todo Temporarily disabled!
        This check does not hold if one of the args
        has been executed but the other one has not.
        Execution here means that Eval(!now) becomes Eval(35353).
        ! is a hacky shorthand for grounded predicates for now.

        The real solution will be tointroduce an equality check which considers
        the unexecuted and executed forms equal.
    */

#if 0

    if (make_vtree(asw->getOutgoing(v2h(premiseArray[0]),0))
        != make_vtree(v2h(premiseArray[1])))
        {
            cprintf(0,"StrictImplicationBreakdownRule args fail:\n");
#if 0
            printTree(v2h(premiseArray[0]),0,0);
            printTree(asw->getOutgoing(v2h(premiseArray[0]),0),0,0);
            printTree(v2h(premiseArray[1]),0,0);

            //      rawPrint(premiseArray[0], premiseArray[0].begin(), 0);
            rawPrint(vt1, vt1.begin(), 0);
            rawPrint(vt2, vt2.begin(), 0);
#else
            printer.print(v2h(premiseArray[0]), -10);
            printer.print(asw->getOutgoing(v2h(premiseArray[0]),0), -10);
            printer.print(v2h(premiseArray[1]), -10);

            //        printer.print(premiseArray[0].begin());
            printer.print(vt1.begin(), -10);
            printer.print(vt2.begin(), -10);
#endif
            assert(0);
        }
#endif

    pHandle implication = _v2h(premiseArray[0]);
    pHandle antecedant = _v2h(premiseArray[1]);
    pHandle conclusion = asw->getOutgoing(implication, 1);

    TruthValue* tvs[] = {
        (TruthValue*) &(asw->getTV(implication)),
        (TruthValue*) &(asw->getTV(antecedant)),
        (TruthValue*) &(asw->getTV(conclusion))
        };

    TruthValue* retTV =
        ImplicationBreakdownFormula().compute(tvs, 3);

    // update the TV of the conclusion.
    // Note that ret is different than conclusion, that is because a dummy
    // context is added and this is translated into a different resulting
    // pHandle (but of course they both correspond to the same atom).
    // See AtomSpaceWrapper.h for more info
    pHandle ret = asw->updateTV(conclusion, *retTV, fresh);

    delete retTV;

    printer.print(ret, 3);

    return Vertex(ret);
}

}} // namespace opencog { namespace pln {
<|endoftext|>


<commit_before>/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrBackendSurface.h"
#include "GrClip.h"
#include "GrContext.h"
#include "GrContextPriv.h"
#include "GrRenderTargetContext.h"
#include "GrTexture.h"
#include "GrTextureAdjuster.h"
#include "SkBitmapCache.h"
#include "SkImage_Gpu.h"
#include "SkImage_GpuBase.h"
#include "SkReadPixelsRec.h"

SkImage_GpuBase::SkImage_GpuBase(sk_sp<GrContext> context, int width, int height, uint32_t uniqueID,
                                 SkAlphaType at, SkBudgeted budgeted, sk_sp<SkColorSpace> cs)
        : INHERITED(width, height, uniqueID)
        , fContext(std::move(context))
        , fAlphaType(at)
        , fBudgeted(budgeted)
        , fColorSpace(std::move(cs)) {}

SkImage_GpuBase::~SkImage_GpuBase() {}

//////////////////////////////////////////////////////////////////////////////////////////////////

bool SkImage_GpuBase::ValidateBackendTexture(GrContext* ctx, const GrBackendTexture& tex,
                                             GrPixelConfig* config, SkColorType ct, SkAlphaType at,
                                             sk_sp<SkColorSpace> cs) {
    if (!tex.isValid()) {
        return false;
    }
    // TODO: Create a SkImageColorInfo struct for color, alpha, and color space so we don't need to
    // create a fake image info here.
    SkImageInfo info = SkImageInfo::Make(1, 1, ct, at, cs);
    if (!SkImageInfoIsValid(info)) {
        return false;
    }

    return ctx->contextPriv().caps()->validateBackendTexture(tex, ct, config);
}

//////////////////////////////////////////////////////////////////////////////////////////////////

bool SkImage_GpuBase::getROPixels(SkBitmap* dst, SkColorSpace*, CachingHint chint) const {
    if (!fContext->contextPriv().resourceProvider()) {
        // DDL TODO: buffer up the readback so it occurs when the DDL is drawn?
        return false;
    }

    // The SkColorSpace parameter "dstColorSpace" is really just a hint about how/where the bitmap
    // will be used. The client doesn't expect that we convert to that color space, it's intended
    // for codec-backed images, to drive our decoding heuristic. In theory we *could* read directly
    // into that color space (to save the client some effort in whatever they're about to do), but
    // that would make our use of the bitmap cache incorrect (or much less efficient, assuming we
    // rolled the dstColorSpace into the key).
    const auto desc = SkBitmapCacheDesc::Make(this);
    if (SkBitmapCache::Find(desc, dst)) {
        SkASSERT(dst->isImmutable());
        SkASSERT(dst->getPixels());
        return true;
    }

    SkBitmapCache::RecPtr rec = nullptr;
    SkPixmap pmap;
    if (kAllow_CachingHint == chint) {
        rec = SkBitmapCache::Alloc(desc, this->onImageInfo(), &pmap);
        if (!rec) {
            return false;
        }
    } else {
        if (!dst->tryAllocPixels(this->onImageInfo()) || !dst->peekPixels(&pmap)) {
            return false;
        }
    }

    sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeWrappedSurfaceContext(
        this->asTextureProxyRef(),
        fColorSpace);
    if (!sContext) {
        return false;
    }

    if (!sContext->readPixels(pmap.info(), pmap.writable_addr(), pmap.rowBytes(), 0, 0)) {
        return false;
    }

    if (rec) {
        SkBitmapCache::Add(std::move(rec), dst);
        this->notifyAddedToRasterCache();
    }
    return true;
}

sk_sp<SkImage> SkImage_GpuBase::onMakeSubset(const SkIRect& subset) const {
    sk_sp<GrSurfaceProxy> proxy = this->asTextureProxyRef();

    GrSurfaceDesc desc;
    desc.fWidth = subset.width();
    desc.fHeight = subset.height();
    desc.fConfig = proxy->config();

    sk_sp<GrSurfaceContext> sContext(fContext->contextPriv().makeDeferredSurfaceContext(
        desc, proxy->origin(), GrMipMapped::kNo, SkBackingFit::kExact, fBudgeted));
    if (!sContext) {
        return nullptr;
    }

    if (!sContext->copy(proxy.get(), subset, SkIPoint::Make(0, 0))) {
        return nullptr;
    }

    // MDB: this call is okay bc we know 'sContext' was kExact
    return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID,
                                   fAlphaType, sContext->asTextureProxyRef(),
                                   fColorSpace, fBudgeted);
}

static void apply_premul(const SkImageInfo& info, void* pixels, size_t rowBytes) {
    switch (info.colorType()) {
    case kRGBA_8888_SkColorType:
    case kBGRA_8888_SkColorType:
        break;
    default:
        return; // nothing to do
    }

    // SkColor is not necesarily RGBA or BGRA, but it is one of them on little-endian,
    // and in either case, the alpha-byte is always in the same place, so we can safely call
    // SkPreMultiplyColor()
    //
    SkColor* row = (SkColor*)pixels;
    for (int y = 0; y < info.height(); ++y) {
        for (int x = 0; x < info.width(); ++x) {
            row[x] = SkPreMultiplyColor(row[x]);
        }
        row = (SkColor*)((char*)(row)+rowBytes);
    }
}

bool SkImage_GpuBase::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
                                   int srcX, int srcY, CachingHint) const {
    if (!fContext->contextPriv().resourceProvider()) {
        // DDL TODO: buffer up the readback so it occurs when the DDL is drawn?
        return false;
    }

    if (!SkImageInfoValidConversion(dstInfo, this->onImageInfo())) {
        return false;
    }

    SkReadPixelsRec rec(dstInfo, dstPixels, dstRB, srcX, srcY);
    if (!rec.trim(this->width(), this->height())) {
        return false;
    }

    // TODO: this seems to duplicate code in GrTextureContext::onReadPixels and
    // GrRenderTargetContext::onReadPixels
    uint32_t flags = 0;
    if (kUnpremul_SkAlphaType == rec.fInfo.alphaType() && kPremul_SkAlphaType == fAlphaType) {
        // let the GPU perform this transformation for us
        flags = GrContextPriv::kUnpremul_PixelOpsFlag;
    }

    sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeWrappedSurfaceContext(
        this->asTextureProxyRef(), fColorSpace);
    if (!sContext) {
        return false;
    }

    if (!sContext->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY, flags)) {
        return false;
    }

    // do we have to manually fix-up the alpha channel?
    //      src         dst
    //      unpremul    premul      fix manually
    //      premul      unpremul    done by kUnpremul_PixelOpsFlag
    // all other combos need to change.
    //
    // Should this be handled by Ganesh? todo:?
    //
    if (kPremul_SkAlphaType == rec.fInfo.alphaType() && kUnpremul_SkAlphaType == fAlphaType) {
        apply_premul(rec.fInfo, rec.fPixels, rec.fRowBytes);
    }
    return true;
}

sk_sp<GrTextureProxy> SkImage_GpuBase::asTextureProxyRef(GrContext* context,
                                                         const GrSamplerState& params,
                                                         SkColorSpace* dstColorSpace,
                                                         sk_sp<SkColorSpace>* texColorSpace,
                                                         SkScalar scaleAdjust[2]) const {
    if (context->uniqueID() != fContext->uniqueID()) {
        SkASSERT(0);
        return nullptr;
    }

    GrTextureAdjuster adjuster(fContext.get(), this->asTextureProxyRef(), fAlphaType,
                               this->uniqueID(), fColorSpace.get());
    return adjuster.refTextureProxyForParams(params, dstColorSpace, texColorSpace, scaleAdjust);
}

GrBackendTexture SkImage_GpuBase::onGetBackendTexture(bool flushPendingGrContextIO,
                                                      GrSurfaceOrigin* origin) const {
    sk_sp<GrTextureProxy> proxy = this->asTextureProxyRef();
    SkASSERT(proxy);

    if (!fContext->contextPriv().resourceProvider() && !proxy->isInstantiated()) {
        // This image was created with a DDL context and cannot be instantiated.
        return GrBackendTexture();
}

    if (!proxy->instantiate(fContext->contextPriv().resourceProvider())) {
        return GrBackendTexture(); // invalid
    }

    GrTexture* texture = proxy->peekTexture();

    if (texture) {
        if (flushPendingGrContextIO) {
            fContext->contextPriv().prepareSurfaceForExternalIO(proxy.get());
        }
        if (origin) {
            *origin = proxy->origin();
        }
        return texture->getBackendTexture();
    }
    return GrBackendTexture(); // invalid
}

GrTexture* SkImage_GpuBase::onGetTexture() const {
    GrTextureProxy* proxy = this->peekProxy();
    if (!proxy) {
        return nullptr;
    }

    sk_sp<GrTextureProxy> proxyRef = this->asTextureProxyRef();
    if (!fContext->contextPriv().resourceProvider() && !proxyRef->isInstantiated()) {
        // This image was created with a DDL context and cannot be instantiated.
        return nullptr;
    }

    if (!proxy->instantiate(fContext->contextPriv().resourceProvider())) {
        return nullptr;
    }

    return proxy->peekTexture();
}

sk_sp<SkImage> SkImage_GpuBase::onMakeColorSpace(sk_sp<SkColorSpace> target) const {
    auto xform = GrColorSpaceXformEffect::Make(fColorSpace.get(), fAlphaType,
                                               target.get(),      fAlphaType);
    if (!xform) {
        return sk_ref_sp(const_cast<SkImage_GpuBase*>(this));
    }

    sk_sp<GrTextureProxy> proxy = this->asTextureProxyRef();

    sk_sp<GrRenderTargetContext> renderTargetContext(
        fContext->contextPriv().makeDeferredRenderTargetContextWithFallback(
            SkBackingFit::kExact, this->width(), this->height(), proxy->config(), nullptr));
    if (!renderTargetContext) {
        return nullptr;
    }

    GrPaint paint;
    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
    paint.addColorTextureProcessor(std::move(proxy), SkMatrix::I());
    paint.addColorFragmentProcessor(std::move(xform));

    const SkRect rect = SkRect::MakeIWH(this->width(), this->height());

    renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect);

    if (!renderTargetContext->asTextureProxy()) {
        return nullptr;
    }

    // MDB: this call is okay bc we know 'renderTargetContext' was exact
    return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID,
                                   fAlphaType, renderTargetContext->asTextureProxyRef(),
                                   std::move(target), fBudgeted);
}

bool SkImage_GpuBase::onIsValid(GrContext* context) const {
    // The base class has already checked that context isn't abandoned (if it's not nullptr)
    if (fContext->abandoned()) {
        return false;
    }

    if (context && context != fContext.get()) {
        return false;
    }

    return true;
}

/////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<GrTexture> SkPromiseImageHelper::getTexture(GrResourceProvider* resourceProvider,
                                                  GrPixelConfig config) {
    // Releases the promise helper if there are no outstanding hard refs. This means that we
    // don't have any ReleaseProcs waiting to be called so we will need to do a fulfill.
    if (fReleaseHelper && fReleaseHelper->weak_expired()) {
        this->resetReleaseHelper();
    }

    sk_sp<GrTexture> tex;
    if (!fReleaseHelper) {
        fFulfillProc(fContext, &fBackendTex);
        fBackendTex.fConfig = config;
        if (!fBackendTex.isValid()) {
            // Even though the GrBackendTexture is not valid, we must call the release
            // proc to keep our contract of always calling Fulfill and Release in pairs.
            fReleaseProc(fContext);
            return sk_sp<GrTexture>();
        }

        tex = resourceProvider->wrapBackendTexture(fBackendTex, kBorrow_GrWrapOwnership);
        if (!tex) {
            // Even though the GrBackendTexture is not valid, we must call the release
            // proc to keep our contract of always calling Fulfill and Release in pairs.
            fReleaseProc(fContext);
            return sk_sp<GrTexture>();
        }
        fReleaseHelper = new SkPromiseReleaseProcHelper(fReleaseProc, fContext, fDoneHelper);
        // Take a weak ref
        fReleaseHelper->weak_ref();
    } else {
        SkASSERT(fBackendTex.isValid());
        tex = resourceProvider->wrapBackendTexture(fBackendTex, kBorrow_GrWrapOwnership);
        if (!tex) {
            // We weren't able to make a texture here, but since we are in this branch
            // of the calls (promiseHelper.fReleaseHelper is valid) there is already a
            // texture out there which will call the release proc so we don't need to
            // call it here.
            return sk_sp<GrTexture>();
        }

        SkAssertResult(fReleaseHelper->try_ref());
    }
    SkASSERT(tex);
    // Pass the hard ref off to the texture
    tex->setRelease(sk_sp<GrReleaseProcHelper>(fReleaseHelper));
    return tex;
}
<commit_msg>Revert "Fix bug with makeColorSpace of GPU images with non-renderable configs"<commit_after>/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrBackendSurface.h"
#include "GrClip.h"
#include "GrContext.h"
#include "GrContextPriv.h"
#include "GrRenderTargetContext.h"
#include "GrTexture.h"
#include "GrTextureAdjuster.h"
#include "SkBitmapCache.h"
#include "SkImage_Gpu.h"
#include "SkImage_GpuBase.h"
#include "SkReadPixelsRec.h"

SkImage_GpuBase::SkImage_GpuBase(sk_sp<GrContext> context, int width, int height, uint32_t uniqueID,
                                 SkAlphaType at, SkBudgeted budgeted, sk_sp<SkColorSpace> cs)
        : INHERITED(width, height, uniqueID)
        , fContext(std::move(context))
        , fAlphaType(at)
        , fBudgeted(budgeted)
        , fColorSpace(std::move(cs)) {}

SkImage_GpuBase::~SkImage_GpuBase() {}

//////////////////////////////////////////////////////////////////////////////////////////////////

bool SkImage_GpuBase::ValidateBackendTexture(GrContext* ctx, const GrBackendTexture& tex,
                                             GrPixelConfig* config, SkColorType ct, SkAlphaType at,
                                             sk_sp<SkColorSpace> cs) {
    if (!tex.isValid()) {
        return false;
    }
    // TODO: Create a SkImageColorInfo struct for color, alpha, and color space so we don't need to
    // create a fake image info here.
    SkImageInfo info = SkImageInfo::Make(1, 1, ct, at, cs);
    if (!SkImageInfoIsValid(info)) {
        return false;
    }

    return ctx->contextPriv().caps()->validateBackendTexture(tex, ct, config);
}

//////////////////////////////////////////////////////////////////////////////////////////////////

bool SkImage_GpuBase::getROPixels(SkBitmap* dst, SkColorSpace*, CachingHint chint) const {
    if (!fContext->contextPriv().resourceProvider()) {
        // DDL TODO: buffer up the readback so it occurs when the DDL is drawn?
        return false;
    }

    // The SkColorSpace parameter "dstColorSpace" is really just a hint about how/where the bitmap
    // will be used. The client doesn't expect that we convert to that color space, it's intended
    // for codec-backed images, to drive our decoding heuristic. In theory we *could* read directly
    // into that color space (to save the client some effort in whatever they're about to do), but
    // that would make our use of the bitmap cache incorrect (or much less efficient, assuming we
    // rolled the dstColorSpace into the key).
    const auto desc = SkBitmapCacheDesc::Make(this);
    if (SkBitmapCache::Find(desc, dst)) {
        SkASSERT(dst->isImmutable());
        SkASSERT(dst->getPixels());
        return true;
    }

    SkBitmapCache::RecPtr rec = nullptr;
    SkPixmap pmap;
    if (kAllow_CachingHint == chint) {
        rec = SkBitmapCache::Alloc(desc, this->onImageInfo(), &pmap);
        if (!rec) {
            return false;
        }
    } else {
        if (!dst->tryAllocPixels(this->onImageInfo()) || !dst->peekPixels(&pmap)) {
            return false;
        }
    }

    sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeWrappedSurfaceContext(
        this->asTextureProxyRef(),
        fColorSpace);
    if (!sContext) {
        return false;
    }

    if (!sContext->readPixels(pmap.info(), pmap.writable_addr(), pmap.rowBytes(), 0, 0)) {
        return false;
    }

    if (rec) {
        SkBitmapCache::Add(std::move(rec), dst);
        this->notifyAddedToRasterCache();
    }
    return true;
}

sk_sp<SkImage> SkImage_GpuBase::onMakeSubset(const SkIRect& subset) const {
    sk_sp<GrSurfaceProxy> proxy = this->asTextureProxyRef();

    GrSurfaceDesc desc;
    desc.fWidth = subset.width();
    desc.fHeight = subset.height();
    desc.fConfig = proxy->config();

    sk_sp<GrSurfaceContext> sContext(fContext->contextPriv().makeDeferredSurfaceContext(
        desc, proxy->origin(), GrMipMapped::kNo, SkBackingFit::kExact, fBudgeted));
    if (!sContext) {
        return nullptr;
    }

    if (!sContext->copy(proxy.get(), subset, SkIPoint::Make(0, 0))) {
        return nullptr;
    }

    // MDB: this call is okay bc we know 'sContext' was kExact
    return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID,
                                   fAlphaType, sContext->asTextureProxyRef(),
                                   fColorSpace, fBudgeted);
}

static void apply_premul(const SkImageInfo& info, void* pixels, size_t rowBytes) {
    switch (info.colorType()) {
    case kRGBA_8888_SkColorType:
    case kBGRA_8888_SkColorType:
        break;
    default:
        return; // nothing to do
    }

    // SkColor is not necesarily RGBA or BGRA, but it is one of them on little-endian,
    // and in either case, the alpha-byte is always in the same place, so we can safely call
    // SkPreMultiplyColor()
    //
    SkColor* row = (SkColor*)pixels;
    for (int y = 0; y < info.height(); ++y) {
        for (int x = 0; x < info.width(); ++x) {
            row[x] = SkPreMultiplyColor(row[x]);
        }
        row = (SkColor*)((char*)(row)+rowBytes);
    }
}

bool SkImage_GpuBase::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
                                   int srcX, int srcY, CachingHint) const {
    if (!fContext->contextPriv().resourceProvider()) {
        // DDL TODO: buffer up the readback so it occurs when the DDL is drawn?
        return false;
    }

    if (!SkImageInfoValidConversion(dstInfo, this->onImageInfo())) {
        return false;
    }

    SkReadPixelsRec rec(dstInfo, dstPixels, dstRB, srcX, srcY);
    if (!rec.trim(this->width(), this->height())) {
        return false;
    }

    // TODO: this seems to duplicate code in GrTextureContext::onReadPixels and
    // GrRenderTargetContext::onReadPixels
    uint32_t flags = 0;
    if (kUnpremul_SkAlphaType == rec.fInfo.alphaType() && kPremul_SkAlphaType == fAlphaType) {
        // let the GPU perform this transformation for us
        flags = GrContextPriv::kUnpremul_PixelOpsFlag;
    }

    sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeWrappedSurfaceContext(
        this->asTextureProxyRef(), fColorSpace);
    if (!sContext) {
        return false;
    }

    if (!sContext->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY, flags)) {
        return false;
    }

    // do we have to manually fix-up the alpha channel?
    //      src         dst
    //      unpremul    premul      fix manually
    //      premul      unpremul    done by kUnpremul_PixelOpsFlag
    // all other combos need to change.
    //
    // Should this be handled by Ganesh? todo:?
    //
    if (kPremul_SkAlphaType == rec.fInfo.alphaType() && kUnpremul_SkAlphaType == fAlphaType) {
        apply_premul(rec.fInfo, rec.fPixels, rec.fRowBytes);
    }
    return true;
}

sk_sp<GrTextureProxy> SkImage_GpuBase::asTextureProxyRef(GrContext* context,
                                                         const GrSamplerState& params,
                                                         SkColorSpace* dstColorSpace,
                                                         sk_sp<SkColorSpace>* texColorSpace,
                                                         SkScalar scaleAdjust[2]) const {
    if (context->uniqueID() != fContext->uniqueID()) {
        SkASSERT(0);
        return nullptr;
    }

    GrTextureAdjuster adjuster(fContext.get(), this->asTextureProxyRef(), fAlphaType,
                               this->uniqueID(), fColorSpace.get());
    return adjuster.refTextureProxyForParams(params, dstColorSpace, texColorSpace, scaleAdjust);
}

GrBackendTexture SkImage_GpuBase::onGetBackendTexture(bool flushPendingGrContextIO,
                                                      GrSurfaceOrigin* origin) const {
    sk_sp<GrTextureProxy> proxy = this->asTextureProxyRef();
    SkASSERT(proxy);

    if (!fContext->contextPriv().resourceProvider() && !proxy->isInstantiated()) {
        // This image was created with a DDL context and cannot be instantiated.
        return GrBackendTexture();
}

    if (!proxy->instantiate(fContext->contextPriv().resourceProvider())) {
        return GrBackendTexture(); // invalid
    }

    GrTexture* texture = proxy->peekTexture();

    if (texture) {
        if (flushPendingGrContextIO) {
            fContext->contextPriv().prepareSurfaceForExternalIO(proxy.get());
        }
        if (origin) {
            *origin = proxy->origin();
        }
        return texture->getBackendTexture();
    }
    return GrBackendTexture(); // invalid
}

GrTexture* SkImage_GpuBase::onGetTexture() const {
    GrTextureProxy* proxy = this->peekProxy();
    if (!proxy) {
        return nullptr;
    }

    sk_sp<GrTextureProxy> proxyRef = this->asTextureProxyRef();
    if (!fContext->contextPriv().resourceProvider() && !proxyRef->isInstantiated()) {
        // This image was created with a DDL context and cannot be instantiated.
        return nullptr;
    }

    if (!proxy->instantiate(fContext->contextPriv().resourceProvider())) {
        return nullptr;
    }

    return proxy->peekTexture();
}

sk_sp<SkImage> SkImage_GpuBase::onMakeColorSpace(sk_sp<SkColorSpace> target) const {
    auto xform = GrColorSpaceXformEffect::Make(fColorSpace.get(), fAlphaType,
                                               target.get(),      fAlphaType);
    if (!xform) {
        return sk_ref_sp(const_cast<SkImage_GpuBase*>(this));
    }

    sk_sp<GrTextureProxy> proxy = this->asTextureProxyRef();

    sk_sp<GrRenderTargetContext> renderTargetContext(
        fContext->contextPriv().makeDeferredRenderTargetContext(
            SkBackingFit::kExact, this->width(), this->height(), proxy->config(), nullptr));
    if (!renderTargetContext) {
        return nullptr;
    }

    GrPaint paint;
    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
    paint.addColorTextureProcessor(std::move(proxy), SkMatrix::I());
    paint.addColorFragmentProcessor(std::move(xform));

    const SkRect rect = SkRect::MakeIWH(this->width(), this->height());

    renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect);

    if (!renderTargetContext->asTextureProxy()) {
        return nullptr;
    }

    // MDB: this call is okay bc we know 'renderTargetContext' was exact
    return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID,
                                   fAlphaType, renderTargetContext->asTextureProxyRef(),
                                   std::move(target), fBudgeted);
}

bool SkImage_GpuBase::onIsValid(GrContext* context) const {
    // The base class has already checked that context isn't abandoned (if it's not nullptr)
    if (fContext->abandoned()) {
        return false;
    }

    if (context && context != fContext.get()) {
        return false;
    }

    return true;
}

/////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<GrTexture> SkPromiseImageHelper::getTexture(GrResourceProvider* resourceProvider,
                                                  GrPixelConfig config) {
    // Releases the promise helper if there are no outstanding hard refs. This means that we
    // don't have any ReleaseProcs waiting to be called so we will need to do a fulfill.
    if (fReleaseHelper && fReleaseHelper->weak_expired()) {
        this->resetReleaseHelper();
    }

    sk_sp<GrTexture> tex;
    if (!fReleaseHelper) {
        fFulfillProc(fContext, &fBackendTex);
        fBackendTex.fConfig = config;
        if (!fBackendTex.isValid()) {
            // Even though the GrBackendTexture is not valid, we must call the release
            // proc to keep our contract of always calling Fulfill and Release in pairs.
            fReleaseProc(fContext);
            return sk_sp<GrTexture>();
        }

        tex = resourceProvider->wrapBackendTexture(fBackendTex, kBorrow_GrWrapOwnership);
        if (!tex) {
            // Even though the GrBackendTexture is not valid, we must call the release
            // proc to keep our contract of always calling Fulfill and Release in pairs.
            fReleaseProc(fContext);
            return sk_sp<GrTexture>();
        }
        fReleaseHelper = new SkPromiseReleaseProcHelper(fReleaseProc, fContext, fDoneHelper);
        // Take a weak ref
        fReleaseHelper->weak_ref();
    } else {
        SkASSERT(fBackendTex.isValid());
        tex = resourceProvider->wrapBackendTexture(fBackendTex, kBorrow_GrWrapOwnership);
        if (!tex) {
            // We weren't able to make a texture here, but since we are in this branch
            // of the calls (promiseHelper.fReleaseHelper is valid) there is already a
            // texture out there which will call the release proc so we don't need to
            // call it here.
            return sk_sp<GrTexture>();
        }

        SkAssertResult(fReleaseHelper->try_ref());
    }
    SkASSERT(tex);
    // Pass the hard ref off to the texture
    tex->setRelease(sk_sp<GrReleaseProcHelper>(fReleaseHelper));
    return tex;
}
<|endoftext|>


<commit_before>//---------------------------------------------------------------------------//
//!
//! \file   MonteCarlo_CollisionHandler.cpp
//! \author Alex Robinson
//! \brief  Collision handler class definition.
//!
//---------------------------------------------------------------------------//

// Std Lib Includes
#include <stdexcept>

// FRENSIE Includes
#include "MonteCarlo_CollisionHandler.hpp"
#include "Utility_ExceptionTestMacros.hpp"
#include "Utility_ContractException.hpp"

namespace MonteCarlo{

// Initialize the static member data
CollisionHandler::CellIdNeutronMaterialMap
CollisionHandler::master_neutron_map;

CollisionHandler::CellIdPhotonMaterialMap
CollisionHandler::master_photon_map;

// Add a material to the collision handler
void CollisionHandler::addMaterial(
	      const Teuchos::RCP<NeutronMaterial>& material,
	      const Teuchos::Array<Geometry::ModuleTraits::InternalCellHandle>&
	      cells_containing_material )
{
  // Make sure the material pointer is valid
  testPrecondition( !material.is_null() );
  // Make sure the cells are valid
  testPrecondition( cells_containing_material.size() > 0 );

  for( unsigned i = 0u; i < cells_containing_material.size(); ++i )
  {
    TEST_FOR_EXCEPTION(
      CollisionHandler::master_neutron_map.find(cells_containing_material[i])!=
				    CollisionHandler::master_neutron_map.end(),
      std::logic_error,
      "Error: cell " << cells_containing_material[i] << " already has a "
      "material assigned!" );

    CollisionHandler::master_neutron_map[cells_containing_material[i]] =
      material;
  }
}

// Add a material to the collision handler
void CollisionHandler::addMaterial(
	      const Teuchos::RCP<PhotonMaterial>& material,
	      const Teuchos::Array<Geometry::ModuleTraits::InternalCellHandle>&
	      cells_containing_material )
{
  // Make sure the material pointer is valid
  testPrecondition( !material.is_null() );
  // Make sure the cells are valid
  testPrecondition( cells_containing_material.size() > 0 );

  for( unsigned i = 0u; i < cells_containing_material.size(); ++i )
  {
    TEST_FOR_EXCEPTION(
      CollisionHandler::master_photon_map.find(cells_containing_material[i]) !=
      CollisionHandler::master_photon_map.end(),
      std::logic_error,
      "Error:: cell " << cells_containing_material[i] << " already has a "
      "material assigned!" );

    CollisionHandler::master_photon_map[cells_containing_material[i]] =
      material;
  }
}

// Add a material to the collision handler
void CollisionHandler::addMaterial(
	      const Teuchos::RCP<NeutronMaterial>& neutron_material,
	      const Teuchos::RCP<PhotonMaterial>& photon_material,
	      const Teuchos::Array<Geometry::ModuleTraits::InternalCellHandle>&
	      cells_containing_material )
{
  // Make sure the material pointers are valid
  testPrecondition( !neutron_material.is_null() );
  testPrecondition( !photon_material.is_null() );
  // Make sure the cells are valid
  testPrecondition( cells_containing_material.size() > 0 );

  CollisionHandler::addMaterial( neutron_material, cells_containing_material );

  CollisionHandler::addMaterial( photon_material, cells_containing_material );
}

// Check if a cell is void
bool CollisionHandler::isCellVoid(
			 const Geometry::ModuleTraits::InternalCellHandle cell,
			 const ParticleType particle_type )
{
  switch( particle_type )
  {
  case NEUTRON:
    if( CollisionHandler::master_neutron_map.find( cell ) ==
      CollisionHandler::master_neutron_map.end() )
      return true;
    else
      return false;
  case PHOTON:
    if( CollisionHandler::master_photon_map.find( cell ) ==
	CollisionHandler::master_photon_map.end() )
      return true;
    else
      return false;
  default:
    return true;
  }
}

// Get the neutron material contained in a cell
const Teuchos::RCP<NeutronMaterial>&
CollisionHandler::getCellNeutronMaterial(
			const Geometry::ModuleTraits::InternalCellHandle cell )
{
  // Make sure the cell is not void
  testPrecondition( !CollisionHandler::isCellVoid( cell, NEUTRON ) );

  return CollisionHandler::master_neutron_map.find( cell )->second;
}

// Get the photon material contained in a cell
const Teuchos::RCP<PhotonMaterial>&
CollisionHandler::getCellPhotonMaterial(
			const Geometry::ModuleTraits::InternalCellHandle cell )
{
  // Make sure the cell is not void
  testPrecondition( !CollisionHandler::isCellVoid( cell, PHOTON ) );

  return CollisionHandler::master_photon_map.find( cell )->second;
}

// Get the total macroscopic cross section of a material
double CollisionHandler::getMacroscopicTotalCrossSection(
						const NeutronState& particle )
{
  // Make sure the cell is not void
  testPrecondition( !CollisionHandler::isCellVoid( particle.getCell(),
						   NEUTRON ) );

  Teuchos::RCP<NeutronMaterial>& material =
    CollisionHandler::master_neutron_map.find( particle.getCell() )->second;
}

// Get the total macroscopic cross section of a material
double CollisionHandler::getMacroscopicTotalCrossSection(
						  const PhotonState& particle )
{
  // Make sure the cell is not void
  testPrecondition( !CollisionHandler::isCellVoid( particle.getCell(),
						   PHOTON ) );

  Teuchos::RCP<PhotonMaterial>& material =
      CollisionHandler::master_photon_map.find( particle.getCell() )->second;

  return material->getMacroscopicTotalCrossSection( particle.getEnergy() );
}

// Get the macroscopic cross section for a specific reaction
double CollisionHandler::getMacroscopicReactionCrossSection(
					   const NeutronState& particle,
					   const NuclearReactionType reaction )
{
  CellIdNeutronMaterialMap::const_iterator it =
    CollisionHandler::master_neutron_map.find( particle.getCell() );

  if( it != CollisionHandler::master_neutron_map.end() )
  {
    return it->second->getMacroscopicReactionCrossSection(particle.getEnergy(),
							  reaction );
  }
  else
    return 0.0;
}

// Get the macroscopic cross section for a specific reaction
double CollisionHandler::getMacroscopicReactionCrossSection(
				      const PhotonState& particle,
				      const PhotoatomicReactionType reaction )
{
  CellIdPhotonMaterialMap::const_iterator it =
    CollisionHandler::master_photon_map.find( particle.getCell() );

  if( it != CollisionHandler::master_photon_map.end() )
  {
    return it->second->getMacroscopicReactionCrossSection(particle.getEnergy(),
							  reaction );
  }
  else
    return 0.0;
}

// Get the macroscopic cross section for a specific reaction
double CollisionHandler::getMacroscopicReactionCrossSection(
				      const PhotonState& particle,
				      const PhotonuclearReactionType reaction )
{
  CellIdPhotonMaterialMap::const_iterator it =
    CollisionHandler::master_photon_map.find( particle.getCell() );

  if( it != CollisionHandler::master_photon_map.end() )
  {
    return it->second->getMacroscopicReactionCrossSection(particle.getEnergy(),
							  reaction );
  }
  else
    return 0.0;
}

// Collide with the material in a cell
void CollisionHandler::collideWithCellMaterial( NeutronState& particle,
						ParticleBank& bank,
						const bool analogue )
{
  // Make sure the cell is not void
  testPrecondition( !CollisionHandler::isCellVoid( particle.getCell(),
						   NEUTRON ) );

  const Teuchos::RCP<NeutronMaterial>& material =
    CollisionHandler::master_neutron_map.find( particle.getCell() )->second;

  if( analogue )
    material->collideAnalogue( particle, bank );
  else
    material->collideSurvivalBias( particle, bank );
}

// Collide with the material in a cell
void CollisionHandler::collideWithCellMaterial( PhotonState& particle,
						ParticleBank& bank,
						const bool analogue )
{
  // Make sure the cell is not void
  testPrecondition( !CollisionHandler::isCellVoid( particle.getCell(),
						   PHOTON ) );

  const Teuchos::RCP<PhotonMaterial>& material =
    CollisionHandler::master_photon_map.find( particle.getCell() )->second;

  if( analogue )
    material->collideAnalogue( particle, bank );
  else
    material->collideSurvivalBias( particle, bank );
}

} // end MonteCarlo namespace

//---------------------------------------------------------------------------//
// end MonteCarlo_CollisionHandler.cpp
//---------------------------------------------------------------------------//
<commit_msg>Fixed broken collision handler unit tests.<commit_after>//---------------------------------------------------------------------------//
//!
//! \file   MonteCarlo_CollisionHandler.cpp
//! \author Alex Robinson
//! \brief  Collision handler class definition.
//!
//---------------------------------------------------------------------------//

// Std Lib Includes
#include <stdexcept>

// FRENSIE Includes
#include "MonteCarlo_CollisionHandler.hpp"
#include "Utility_ExceptionTestMacros.hpp"
#include "Utility_ContractException.hpp"

namespace MonteCarlo{

// Initialize the static member data
CollisionHandler::CellIdNeutronMaterialMap
CollisionHandler::master_neutron_map;

CollisionHandler::CellIdPhotonMaterialMap
CollisionHandler::master_photon_map;

// Add a material to the collision handler
void CollisionHandler::addMaterial(
	      const Teuchos::RCP<NeutronMaterial>& material,
	      const Teuchos::Array<Geometry::ModuleTraits::InternalCellHandle>&
	      cells_containing_material )
{
  // Make sure the material pointer is valid
  testPrecondition( !material.is_null() );
  // Make sure the cells are valid
  testPrecondition( cells_containing_material.size() > 0 );

  for( unsigned i = 0u; i < cells_containing_material.size(); ++i )
  {
    TEST_FOR_EXCEPTION(
      CollisionHandler::master_neutron_map.find(cells_containing_material[i])!=
				    CollisionHandler::master_neutron_map.end(),
      std::logic_error,
      "Error: cell " << cells_containing_material[i] << " already has a "
      "material assigned!" );

    CollisionHandler::master_neutron_map[cells_containing_material[i]] =
      material;
  }
}

// Add a material to the collision handler
void CollisionHandler::addMaterial(
	      const Teuchos::RCP<PhotonMaterial>& material,
	      const Teuchos::Array<Geometry::ModuleTraits::InternalCellHandle>&
	      cells_containing_material )
{
  // Make sure the material pointer is valid
  testPrecondition( !material.is_null() );
  // Make sure the cells are valid
  testPrecondition( cells_containing_material.size() > 0 );

  for( unsigned i = 0u; i < cells_containing_material.size(); ++i )
  {
    TEST_FOR_EXCEPTION(
      CollisionHandler::master_photon_map.find(cells_containing_material[i]) !=
      CollisionHandler::master_photon_map.end(),
      std::logic_error,
      "Error:: cell " << cells_containing_material[i] << " already has a "
      "material assigned!" );

    CollisionHandler::master_photon_map[cells_containing_material[i]] =
      material;
  }
}

// Add a material to the collision handler
void CollisionHandler::addMaterial(
	      const Teuchos::RCP<NeutronMaterial>& neutron_material,
	      const Teuchos::RCP<PhotonMaterial>& photon_material,
	      const Teuchos::Array<Geometry::ModuleTraits::InternalCellHandle>&
	      cells_containing_material )
{
  // Make sure the material pointers are valid
  testPrecondition( !neutron_material.is_null() );
  testPrecondition( !photon_material.is_null() );
  // Make sure the cells are valid
  testPrecondition( cells_containing_material.size() > 0 );

  CollisionHandler::addMaterial( neutron_material, cells_containing_material );

  CollisionHandler::addMaterial( photon_material, cells_containing_material );
}

// Check if a cell is void
bool CollisionHandler::isCellVoid(
			 const Geometry::ModuleTraits::InternalCellHandle cell,
			 const ParticleType particle_type )
{
  switch( particle_type )
  {
  case NEUTRON:
    if( CollisionHandler::master_neutron_map.find( cell ) ==
      CollisionHandler::master_neutron_map.end() )
      return true;
    else
      return false;
  case PHOTON:
    if( CollisionHandler::master_photon_map.find( cell ) ==
	CollisionHandler::master_photon_map.end() )
      return true;
    else
      return false;
  default:
    return true;
  }
}

// Get the neutron material contained in a cell
const Teuchos::RCP<NeutronMaterial>&
CollisionHandler::getCellNeutronMaterial(
			const Geometry::ModuleTraits::InternalCellHandle cell )
{
  // Make sure the cell is not void
  testPrecondition( !CollisionHandler::isCellVoid( cell, NEUTRON ) );

  return CollisionHandler::master_neutron_map.find( cell )->second;
}

// Get the photon material contained in a cell
const Teuchos::RCP<PhotonMaterial>&
CollisionHandler::getCellPhotonMaterial(
			const Geometry::ModuleTraits::InternalCellHandle cell )
{
  // Make sure the cell is not void
  testPrecondition( !CollisionHandler::isCellVoid( cell, PHOTON ) );

  return CollisionHandler::master_photon_map.find( cell )->second;
}

// Get the total macroscopic cross section of a material
double CollisionHandler::getMacroscopicTotalCrossSection(
						const NeutronState& particle )
{
  // Make sure the cell is not void
  testPrecondition( !CollisionHandler::isCellVoid( particle.getCell(),
						   NEUTRON ) );

  Teuchos::RCP<NeutronMaterial>& material =
    CollisionHandler::master_neutron_map.find( particle.getCell() )->second;

  return material->getMacroscopicTotalCrossSection( particle.getEnergy() );
}

// Get the total macroscopic cross section of a material
double CollisionHandler::getMacroscopicTotalCrossSection(
						  const PhotonState& particle )
{
  // Make sure the cell is not void
  testPrecondition( !CollisionHandler::isCellVoid( particle.getCell(),
						   PHOTON ) );

  Teuchos::RCP<PhotonMaterial>& material =
      CollisionHandler::master_photon_map.find( particle.getCell() )->second;

  return material->getMacroscopicTotalCrossSection( particle.getEnergy() );
}

// Get the macroscopic cross section for a specific reaction
double CollisionHandler::getMacroscopicReactionCrossSection(
					   const NeutronState& particle,
					   const NuclearReactionType reaction )
{
  CellIdNeutronMaterialMap::const_iterator it =
    CollisionHandler::master_neutron_map.find( particle.getCell() );

  if( it != CollisionHandler::master_neutron_map.end() )
  {
    return it->second->getMacroscopicReactionCrossSection(particle.getEnergy(),
							  reaction );
  }
  else
    return 0.0;
}

// Get the macroscopic cross section for a specific reaction
double CollisionHandler::getMacroscopicReactionCrossSection(
				      const PhotonState& particle,
				      const PhotoatomicReactionType reaction )
{
  CellIdPhotonMaterialMap::const_iterator it =
    CollisionHandler::master_photon_map.find( particle.getCell() );

  if( it != CollisionHandler::master_photon_map.end() )
  {
    return it->second->getMacroscopicReactionCrossSection(particle.getEnergy(),
							  reaction );
  }
  else
    return 0.0;
}

// Get the macroscopic cross section for a specific reaction
double CollisionHandler::getMacroscopicReactionCrossSection(
				      const PhotonState& particle,
				      const PhotonuclearReactionType reaction )
{
  CellIdPhotonMaterialMap::const_iterator it =
    CollisionHandler::master_photon_map.find( particle.getCell() );

  if( it != CollisionHandler::master_photon_map.end() )
  {
    return it->second->getMacroscopicReactionCrossSection(particle.getEnergy(),
							  reaction );
  }
  else
    return 0.0;
}

// Collide with the material in a cell
void CollisionHandler::collideWithCellMaterial( NeutronState& particle,
						ParticleBank& bank,
						const bool analogue )
{
  // Make sure the cell is not void
  testPrecondition( !CollisionHandler::isCellVoid( particle.getCell(),
						   NEUTRON ) );

  const Teuchos::RCP<NeutronMaterial>& material =
    CollisionHandler::master_neutron_map.find( particle.getCell() )->second;

  if( analogue )
    material->collideAnalogue( particle, bank );
  else
    material->collideSurvivalBias( particle, bank );
}

// Collide with the material in a cell
void CollisionHandler::collideWithCellMaterial( PhotonState& particle,
						ParticleBank& bank,
						const bool analogue )
{
  // Make sure the cell is not void
  testPrecondition( !CollisionHandler::isCellVoid( particle.getCell(),
						   PHOTON ) );

  const Teuchos::RCP<PhotonMaterial>& material =
    CollisionHandler::master_photon_map.find( particle.getCell() )->second;

  if( analogue )
    material->collideAnalogue( particle, bank );
  else
    material->collideSurvivalBias( particle, bank );
}

} // end MonteCarlo namespace

//---------------------------------------------------------------------------//
// end MonteCarlo_CollisionHandler.cpp
//---------------------------------------------------------------------------//
<|endoftext|>