<commit_before>/*
 * Copyright 2015 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * 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 "matrix_algs.h"
#include "combined_matrix_store.h"
#include "cached_matrix_store.h"

namespace fm
{

namespace alg
{

static size_t get_nnz(sparse_matrix::ptr mat)
{
	int num_nodes = matrix_conf.get_num_nodes();
	detail::matrix_store::ptr out_store = detail::matrix_store::create(
			mat->get_num_rows(), 1, matrix_layout_t::L_ROW,
			get_scalar_type<size_t>(), num_nodes, true);
	dense_matrix::ptr one = dense_matrix::create_const<size_t>(1,
			mat->get_num_cols(), 1, matrix_layout_t::L_ROW, num_nodes, true);
	mat->multiply<size_t, size_t>(one->get_raw_store(), out_store);
	dense_matrix::ptr out_deg = dense_matrix::create(out_store);
	scalar_variable::ptr v = out_deg->sum();
	return scalar_variable::get_val<size_t>(*v);
}

// trace of W %*% H
static double trace_MM(dense_matrix::ptr W, dense_matrix::ptr H)
{
	dense_matrix::ptr tH = H->transpose();
	dense_matrix::ptr tmp = W->multiply_ele(*tH);
	scalar_variable::ptr res = tmp->sum();
	return scalar_variable::get_val<double>(*res);
}

static dense_matrix::ptr multiply(sparse_matrix::ptr S, dense_matrix::ptr D,
		size_t num_in_mem)
{
	size_t k = D->get_num_cols();
	dense_matrix::ptr ret;
	if (num_in_mem >= k * 2) {
		detail::mem_matrix_store::ptr res = detail::mem_matrix_store::create(
				S->get_num_rows(), D->get_num_cols(), matrix_layout_t::L_ROW,
				D->get_type(), D->get_raw_store()->get_num_nodes());
		S->multiply<double, double>(D->get_raw_store(), res);
		ret = dense_matrix::create(res);
	}
	else if (num_in_mem > k) {
		detail::matrix_store::ptr res = detail::cached_matrix_store::create(
				S->get_num_rows(), D->get_num_cols(),
				D->get_raw_store()->get_num_nodes(), D->get_type(),
				num_in_mem - k, matrix_layout_t::L_COL);
		S->multiply<double, double>(D->get_raw_store(), res);
		ret = dense_matrix::create(res);
	}
	else if (num_in_mem == k) {
		detail::matrix_store::ptr res = detail::matrix_store::create(
				S->get_num_rows(), D->get_num_cols(), matrix_layout_t::L_ROW,
				D->get_type(), -1, false);
		S->multiply<double, double>(D->get_raw_store(), res);
		D->drop_cache();
		ret = dense_matrix::create(res);
	}
	else {
		std::vector<detail::matrix_store::const_ptr> res_mats;
		for (size_t i = 0; i < k; i += num_in_mem) {
			size_t sub_ncol = std::min(num_in_mem, k - i);
			std::vector<off_t> col_idxs(sub_ncol);
			for (size_t j = 0; j < sub_ncol; j++)
				col_idxs[j] = i + j;
			dense_matrix::ptr sub_in = D->get_cols(col_idxs);
			detail::matrix_store::ptr out = detail::matrix_store::create(
					S->get_num_rows(), sub_in->get_num_cols(),
					matrix_layout_t::L_COL, D->get_type(), -1, false);
			S->multiply<double, double>(sub_in->get_raw_store(), out);
			D->drop_cache();
			res_mats.push_back(out);
		}
		ret = dense_matrix::create(detail::combined_matrix_store::create(
					res_mats, matrix_layout_t::L_COL));
	}
	printf("reserve mem for %ld vecs\n",
			detail::get_reserved_bytes() / D->get_num_rows() / D->get_entry_size());
	return ret;
}

// ||A - W %*% H||^2
static double Fnorm(sparse_matrix::ptr A, size_t Annz, dense_matrix::ptr W,
		dense_matrix::ptr H, dense_matrix::ptr tWW, size_t num_in_mem)
{
	// tAW <- t(A) %*% W
	sparse_matrix::ptr tA = A->transpose();
	dense_matrix::ptr tAW = multiply(tA, W, num_in_mem);

	// tHtWW <- t(H) %*% (t(W) %*% W)
	dense_matrix::ptr tH = H->transpose();
	dense_matrix::ptr tHtWW = tH->multiply(*tWW);

	// sumA2 - 2 * trace.MM(tAW, H) + trace.MM(tHtWW, H)
	// TODO H is read twice in this implementation.
	// TODO tAW doesn't need to be materialized.
	return Annz - 2 * trace_MM(tAW, H) + trace_MM(tHtWW, H);
}

struct nmf_state
{
	dense_matrix::ptr W;
	dense_matrix::ptr H;
	dense_matrix::ptr tWW;

	nmf_state(dense_matrix::ptr W, dense_matrix::ptr H,
			dense_matrix::ptr tWW) {
		this->W = W;
		this->H = H;
		this->tWW = tWW;
	}
};

static detail::matrix_store::ptr create_materialize_store(size_t num_rows,
		size_t num_cols, size_t num_in_mem)
{
	int num_nodes = matrix_conf.get_num_nodes();
	if (num_in_mem >= num_cols)
		return detail::matrix_store::create(num_rows, num_cols,
				matrix_layout_t::L_ROW, get_scalar_type<double>(),
				num_nodes, true);
	else
		return detail::cached_matrix_store::create(num_rows, num_cols,
				num_nodes, get_scalar_type<double>(), num_in_mem,
				matrix_layout_t::L_ROW);
}

static nmf_state update_lee(sparse_matrix::ptr mat, dense_matrix::ptr W,
		dense_matrix::ptr H, dense_matrix::ptr tWW, size_t num_in_mem)
{
	double eps = 10e-9;
	// den <- (t(W) %*% W) %*% H
	dense_matrix::ptr D;
	{
		// t(H)
		dense_matrix::ptr tH = H->transpose();
		// t(H) %*% (t(W) %*% W)
		dense_matrix::ptr tD = tH->multiply(*tWW);
		D = tD->transpose();
	}

	// H <- fm.pmax2(H * t(tA %*% W), eps) / (den + eps)
	{
		sparse_matrix::ptr tmat = mat->transpose();
		// tA %*% W
		dense_matrix::ptr tmp1 = multiply(tmat, W, num_in_mem);
		// t(tA %*% W)
		tmp1 = tmp1->transpose();
		// H * t(tA %*% W)
		assert(tmp1->store_layout() == H->store_layout());
		tmp1 = tmp1->multiply_ele(*H);
		// fm.pmax2(H * t(tA %*% W), eps)
		tmp1 = tmp1->pmax_scalar(eps);
		// den + eps
		dense_matrix::ptr tmp3 = D->add_scalar(eps);
		assert(tmp1->store_layout() == tmp3->store_layout());
		H = tmp1->div(*tmp3);
		// mapply_matrix_store materializes a result in a tall matrix buffer.
		// TODO this might be confusing.
		H->set_materialize_level(materialize_level::MATER_FULL,
				create_materialize_store(H->get_num_cols(), H->get_num_rows(),
					num_in_mem));
	}

	// den <- W %*% (H %*% t(H))
	{
		// t(H)
		dense_matrix::ptr tH = H->transpose();
		// H %*% t(H)
		dense_matrix::ptr tmp1 = H->multiply(*tH);
		D = W->multiply(*tmp1);
	}

	// W <- fm.pmax2(W * (A %*% t(H)), eps) / (den + eps)
	{
		// t(H)
		dense_matrix::ptr tH = H->transpose();
		// A %*% t(H)
		dense_matrix::ptr tmp1 = multiply(mat, tH, num_in_mem);
		// W * (A %*% t(H))
		assert(W->store_layout() == tmp1->store_layout());
		tmp1 = W->multiply_ele(*tmp1);
		// fm.pmax2(W * (A %*% t(H)), eps)
		tmp1 = tmp1->pmax_scalar(eps);
		// den + eps
		dense_matrix::ptr tmp2 = D->add_scalar(eps);
		assert(tmp1->store_layout() == tmp2->store_layout());
		W = tmp1->div(*tmp2);
		W->set_materialize_level(materialize_level::MATER_FULL,
				create_materialize_store(W->get_num_rows(), W->get_num_cols(),
					num_in_mem));
	}

	dense_matrix::ptr tW = W->transpose();
	tWW = tW->multiply(*W);
	// TODO We have to materialize these matrices here.
	// Otherwise, we'll get segmentation fault. Why?
	W->materialize_self();
	H->materialize_self();
	return nmf_state(W, H, tWW);
}

dense_matrix::ptr create_rand_cached(size_t num_rows, size_t num_cols,
		int num_nodes, size_t num_cached, matrix_layout_t cached_layout)
{
	detail::matrix_store::ptr store = detail::cached_matrix_store::create(
			num_rows, num_cols, num_nodes, get_scalar_type<double>(),
			num_cached, cached_layout);
	store->init_randu(scalar_variable_impl<double>(0),
			scalar_variable_impl<double>(1));
	return dense_matrix::create(store);
}

std::pair<dense_matrix::ptr, dense_matrix::ptr> NMF(sparse_matrix::ptr mat,
		size_t k, size_t max_niters, size_t num_in_mem)
{
	if (mat->get_entry_size() > 0) {
		BOOST_LOG_TRIVIAL(error) << "can only handle binary sparse matrix";
		return std::pair<dense_matrix::ptr, dense_matrix::ptr>();
	}
	size_t n = mat->get_num_rows();
	size_t m = mat->get_num_cols();
	size_t nnz = get_nnz(mat);
	int num_nodes = matrix_conf.get_num_nodes();
	dense_matrix::ptr W, H;
	if (num_in_mem >= 2 * k) {
		W = dense_matrix::create_randu<double>(0, 1, n, k,
				matrix_layout_t::L_ROW, num_nodes, true);
		H = dense_matrix::create_randu<double>(0, 1, k, m,
				matrix_layout_t::L_COL, num_nodes, true);
	}
	else if (num_in_mem > k && num_in_mem < 2 * k) {
		W = create_rand_cached(n, k, num_nodes, k, matrix_layout_t::L_ROW);
		H = create_rand_cached(k, m, num_nodes, num_in_mem - k,
				matrix_layout_t::L_ROW);
	}
	else if (num_in_mem == k) {
		W = create_rand_cached(n, k, num_nodes, k, matrix_layout_t::L_ROW);
		H = dense_matrix::create_randu<double>(0, 1, k, m,
				matrix_layout_t::L_COL, num_nodes, false);
	}
	else {
		W = create_rand_cached(n, k, num_nodes, num_in_mem, matrix_layout_t::L_ROW);
		H = dense_matrix::create_randu<double>(0, 1, k, m,
				matrix_layout_t::L_ROW, num_nodes, false);
	}

	dense_matrix::ptr tWW;
	{
		dense_matrix::ptr tW = W->transpose();
		tWW = tW->multiply(*W);
	}
	nmf_state state(W, H, tWW);
	for (size_t i = 0; i < max_niters; i++) {
		struct timeval start, end;
		gettimeofday(&start, NULL);
		state = update_lee(mat, state.W, state.H, state.tWW, num_in_mem);
		gettimeofday(&end, NULL);
		double update_time = time_diff(start, end);
		start = end;
		double dist = Fnorm(mat, nnz, state.W, state.H, state.tWW, num_in_mem);
		gettimeofday(&end, NULL);
		printf("iteration %ld: distance: %f, update time: %.3fs, Fnorm: %.3f\n",
				i, dist, update_time, time_diff(start, end));
	}
	return std::pair<dense_matrix::ptr, dense_matrix::ptr>(state.W, state.H);
}

}

}
<commit_msg>[Matrix]: allow to define data layout of materialized matrix in NMF.<commit_after>/*
 * Copyright 2015 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * 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 "matrix_algs.h"
#include "combined_matrix_store.h"
#include "cached_matrix_store.h"

namespace fm
{

namespace alg
{

static size_t get_nnz(sparse_matrix::ptr mat)
{
	int num_nodes = matrix_conf.get_num_nodes();
	detail::matrix_store::ptr out_store = detail::matrix_store::create(
			mat->get_num_rows(), 1, matrix_layout_t::L_ROW,
			get_scalar_type<size_t>(), num_nodes, true);
	dense_matrix::ptr one = dense_matrix::create_const<size_t>(1,
			mat->get_num_cols(), 1, matrix_layout_t::L_ROW, num_nodes, true);
	mat->multiply<size_t, size_t>(one->get_raw_store(), out_store);
	dense_matrix::ptr out_deg = dense_matrix::create(out_store);
	scalar_variable::ptr v = out_deg->sum();
	return scalar_variable::get_val<size_t>(*v);
}

// trace of W %*% H
static double trace_MM(dense_matrix::ptr W, dense_matrix::ptr H)
{
	dense_matrix::ptr tH = H->transpose();
	dense_matrix::ptr tmp = W->multiply_ele(*tH);
	scalar_variable::ptr res = tmp->sum();
	return scalar_variable::get_val<double>(*res);
}

static dense_matrix::ptr multiply(sparse_matrix::ptr S, dense_matrix::ptr D,
		size_t num_in_mem)
{
	size_t k = D->get_num_cols();
	dense_matrix::ptr ret;
	if (num_in_mem >= k * 2) {
		detail::mem_matrix_store::ptr res = detail::mem_matrix_store::create(
				S->get_num_rows(), D->get_num_cols(), matrix_layout_t::L_ROW,
				D->get_type(), D->get_raw_store()->get_num_nodes());
		S->multiply<double, double>(D->get_raw_store(), res);
		ret = dense_matrix::create(res);
	}
	else if (num_in_mem > k) {
		detail::matrix_store::ptr res = detail::cached_matrix_store::create(
				S->get_num_rows(), D->get_num_cols(),
				D->get_raw_store()->get_num_nodes(), D->get_type(),
				num_in_mem - k, matrix_layout_t::L_COL);
		S->multiply<double, double>(D->get_raw_store(), res);
		ret = dense_matrix::create(res);
	}
	else if (num_in_mem == k) {
		detail::matrix_store::ptr res = detail::matrix_store::create(
				S->get_num_rows(), D->get_num_cols(), matrix_layout_t::L_ROW,
				D->get_type(), -1, false);
		S->multiply<double, double>(D->get_raw_store(), res);
		D->drop_cache();
		ret = dense_matrix::create(res);
	}
	else {
		std::vector<detail::matrix_store::const_ptr> res_mats;
		for (size_t i = 0; i < k; i += num_in_mem) {
			size_t sub_ncol = std::min(num_in_mem, k - i);
			std::vector<off_t> col_idxs(sub_ncol);
			for (size_t j = 0; j < sub_ncol; j++)
				col_idxs[j] = i + j;
			dense_matrix::ptr sub_in = D->get_cols(col_idxs);
			detail::matrix_store::ptr out = detail::matrix_store::create(
					S->get_num_rows(), sub_in->get_num_cols(),
					matrix_layout_t::L_COL, D->get_type(), -1, false);
			S->multiply<double, double>(sub_in->get_raw_store(), out);
			D->drop_cache();
			res_mats.push_back(out);
		}
		ret = dense_matrix::create(detail::combined_matrix_store::create(
					res_mats, matrix_layout_t::L_COL));
	}
	printf("reserve mem for %ld vecs\n",
			detail::get_reserved_bytes() / D->get_num_rows() / D->get_entry_size());
	return ret;
}

// ||A - W %*% H||^2
static double Fnorm(sparse_matrix::ptr A, size_t Annz, dense_matrix::ptr W,
		dense_matrix::ptr H, dense_matrix::ptr tWW, size_t num_in_mem)
{
	// tAW <- t(A) %*% W
	sparse_matrix::ptr tA = A->transpose();
	dense_matrix::ptr tAW = multiply(tA, W, num_in_mem);

	// tHtWW <- t(H) %*% (t(W) %*% W)
	dense_matrix::ptr tH = H->transpose();
	dense_matrix::ptr tHtWW = tH->multiply(*tWW);

	// sumA2 - 2 * trace.MM(tAW, H) + trace.MM(tHtWW, H)
	// TODO H is read twice in this implementation.
	// TODO tAW doesn't need to be materialized.
	return Annz - 2 * trace_MM(tAW, H) + trace_MM(tHtWW, H);
}

struct nmf_state
{
	dense_matrix::ptr W;
	dense_matrix::ptr H;
	dense_matrix::ptr tWW;

	nmf_state(dense_matrix::ptr W, dense_matrix::ptr H,
			dense_matrix::ptr tWW) {
		this->W = W;
		this->H = H;
		this->tWW = tWW;
	}
};

static detail::matrix_store::ptr create_materialize_store(size_t num_rows,
		size_t num_cols, size_t num_in_mem, matrix_layout_t layout)
{
	int num_nodes = matrix_conf.get_num_nodes();
	detail::matrix_store::ptr ret;
	if (num_in_mem < num_cols)
		ret = detail::cached_matrix_store::create(
				num_rows, num_cols, num_nodes, get_scalar_type<double>(),
				std::min(num_in_mem, num_cols), layout);
	else if (num_in_mem < 2 * num_cols)
		ret = detail::cached_matrix_store::create(
				num_rows, num_cols, num_nodes, get_scalar_type<double>(),
				std::min(num_in_mem, num_cols), layout, layout);
	else
		ret = detail::mem_matrix_store::create(num_rows, num_cols, layout,
				get_scalar_type<double>(), num_nodes);
	return ret;
}

static nmf_state update_lee(sparse_matrix::ptr mat, dense_matrix::ptr W,
		dense_matrix::ptr H, dense_matrix::ptr tWW, size_t num_in_mem)
{
	double eps = 10e-9;
	// den <- (t(W) %*% W) %*% H
	dense_matrix::ptr D;
	{
		// t(H)
		dense_matrix::ptr tH = H->transpose();
		// t(H) %*% (t(W) %*% W)
		dense_matrix::ptr tD = tH->multiply(*tWW);
		D = tD->transpose();
	}

	// H <- fm.pmax2(H * t(tA %*% W), eps) / (den + eps)
	{
		sparse_matrix::ptr tmat = mat->transpose();
		// tA %*% W
		dense_matrix::ptr tmp1 = multiply(tmat, W, num_in_mem);

		// t(tA %*% W)
		tmp1 = tmp1->transpose();
		// H * t(tA %*% W)
		assert(tmp1->store_layout() == H->store_layout());
		tmp1 = tmp1->multiply_ele(*H);
		// fm.pmax2(H * t(tA %*% W), eps)
		tmp1 = tmp1->pmax_scalar(eps);
		// den + eps
		dense_matrix::ptr tmp3 = D->add_scalar(eps);
		assert(tmp1->store_layout() == tmp3->store_layout());
		H = tmp1->div(*tmp3);
		// mapply_matrix_store materializes a result in a tall matrix buffer.
		// TODO this might be confusing.
		H->set_materialize_level(materialize_level::MATER_FULL,
				create_materialize_store(H->get_num_cols(), H->get_num_rows(),
					num_in_mem, matrix_layout_t::L_ROW));
	}

	// den <- W %*% (H %*% t(H))
	{
		// t(H)
		dense_matrix::ptr tH = H->transpose();
		// H %*% t(H)
		dense_matrix::ptr tmp1 = H->multiply(*tH);
		D = W->multiply(*tmp1);
	}

	// W <- fm.pmax2(W * (A %*% t(H)), eps) / (den + eps)
	{
		// t(H)
		dense_matrix::ptr tH = H->transpose();
		// A %*% t(H)
		dense_matrix::ptr tmp1 = multiply(mat, tH, num_in_mem);
		// W * (A %*% t(H))
		assert(W->store_layout() == tmp1->store_layout());
		tmp1 = W->multiply_ele(*tmp1);
		// fm.pmax2(W * (A %*% t(H)), eps)
		tmp1 = tmp1->pmax_scalar(eps);
		// den + eps
		dense_matrix::ptr tmp2 = D->add_scalar(eps);
		assert(tmp1->store_layout() == tmp2->store_layout());
		W = tmp1->div(*tmp2);
		W->set_materialize_level(materialize_level::MATER_FULL,
				create_materialize_store(W->get_num_rows(), W->get_num_cols(),
					num_in_mem, matrix_layout_t::L_ROW));
	}

	dense_matrix::ptr tW = W->transpose();
	tWW = tW->multiply(*W);
	// TODO We have to materialize these matrices here.
	// Otherwise, we'll get segmentation fault. Why?
	W->materialize_self();
	H->materialize_self();
	return nmf_state(W, H, tWW);
}

dense_matrix::ptr create_rand_cached(size_t num_rows, size_t num_cols,
		int num_nodes, size_t num_cached, matrix_layout_t cached_layout)
{
	detail::matrix_store::ptr store = detail::cached_matrix_store::create(
			num_rows, num_cols, num_nodes, get_scalar_type<double>(),
			num_cached, cached_layout);
	store->init_randu(scalar_variable_impl<double>(0),
			scalar_variable_impl<double>(1));
	return dense_matrix::create(store);
}

std::pair<dense_matrix::ptr, dense_matrix::ptr> NMF(sparse_matrix::ptr mat,
		size_t k, size_t max_niters, size_t num_in_mem)
{
	if (mat->get_entry_size() > 0) {
		BOOST_LOG_TRIVIAL(error) << "can only handle binary sparse matrix";
		return std::pair<dense_matrix::ptr, dense_matrix::ptr>();
	}
	size_t n = mat->get_num_rows();
	size_t m = mat->get_num_cols();
	size_t nnz = get_nnz(mat);
	int num_nodes = matrix_conf.get_num_nodes();
	dense_matrix::ptr W, H;
	if (num_in_mem >= 2 * k) {
		W = dense_matrix::create_randu<double>(0, 1, n, k,
				matrix_layout_t::L_ROW, num_nodes, true);
		H = dense_matrix::create_randu<double>(0, 1, k, m,
				matrix_layout_t::L_COL, num_nodes, true);
	}
	else if (num_in_mem > k && num_in_mem < 2 * k) {
		W = create_rand_cached(n, k, num_nodes, k, matrix_layout_t::L_ROW);
		H = create_rand_cached(k, m, num_nodes, num_in_mem - k,
				matrix_layout_t::L_ROW);
	}
	else if (num_in_mem == k) {
		W = create_rand_cached(n, k, num_nodes, k, matrix_layout_t::L_ROW);
		H = dense_matrix::create_randu<double>(0, 1, k, m,
				matrix_layout_t::L_COL, num_nodes, false);
	}
	else {
		W = create_rand_cached(n, k, num_nodes, num_in_mem, matrix_layout_t::L_ROW);
		H = dense_matrix::create_randu<double>(0, 1, k, m,
				matrix_layout_t::L_ROW, num_nodes, false);
	}

	dense_matrix::ptr tWW;
	{
		dense_matrix::ptr tW = W->transpose();
		tWW = tW->multiply(*W);
	}
	nmf_state state(W, H, tWW);
	for (size_t i = 0; i < max_niters; i++) {
		struct timeval start, end;
		gettimeofday(&start, NULL);
		state = update_lee(mat, state.W, state.H, state.tWW, num_in_mem);
		gettimeofday(&end, NULL);
		double update_time = time_diff(start, end);
		start = end;
		double dist = Fnorm(mat, nnz, state.W, state.H, state.tWW, num_in_mem);
		gettimeofday(&end, NULL);
		printf("iteration %ld: distance: %f, update time: %.3fs, Fnorm: %.3f\n",
				i, dist, update_time, time_diff(start, end));
	}
	return std::pair<dense_matrix::ptr, dense_matrix::ptr>(state.W, state.H);
}

}

}
<|endoftext|>


<commit_before>//  Copyright [2015] <kangic21@gmail.com>

#include "udp_socket.h"
#include "event/event.h"
#include "event/event_dispatcher.h"

#include <cstring>

namespace eznetpp {
namespace net {
namespace udp {

udp_socket::udp_socket(void) {
  _sock_domain = socket_domain::inet_v4;
  _sock_type = socket_type::udp;

  // TODO : implement for PF_INET6
  _sd = ::socket(_sock_domain, _sock_type, 0);

  set_nonblocking();
}

udp_socket::~udp_socket(void) {
}

int udp_socket::open(int port) {
  int ret = bind(port);

  if (ret != 0)
    return ret;

  set_reuseaddr();

  return 0;
}

void udp_socket::send(void) {
  if (_sd == -1)
    return;

  {
    std::lock_guard<std::mutex> lock(_sendmsgs_mtx);
    // step 1. check the send message vector's size
    // if it isn't empty, start the loop statement to send the message.

    while (!_sendmsgs_vec.empty()) {
      // step 2. pop a message from the send message's vector
      std::string msg = _sendmsgs_vec[0].first;
      eznetpp::net::peer_addr pi = _sendmsgs_vec[0].second;
      _sendmsgs_vec.erase(_sendmsgs_vec.begin());

      // step 3. send the message and check an error case
      struct sockaddr_in client_addr;
      bzero(&client_addr, sizeof(client_addr));
      client_addr.sin_addr.s_addr = inet_addr(pi.ip.c_str());
      client_addr.sin_port = htons(pi.port);
      int ret = ::sendto(_sd, msg.c_str(), msg.length(), 0
          , (struct sockaddr *)&client_addr, sizeof(client_addr));
      if (ret == -1) {
        // error check
        if (errno == EAGAIN) {
          std::this_thread::sleep_for(std::chrono::milliseconds(1));
          continue;
        }

        break;
      }
      if (ret > 0) {
        eznetpp::event::event_dispatcher::instance().push_event(
            new eznetpp::event::io_event(eznetpp::event::event_type::udp_sendto
              , ret, errno, this));
      }
    }
  } // lock_guard

  if (set_epollout_flag(false) == -1)
      eznetpp::util::logger::instance().log(eznetpp::util::logger::log_level::error
          , __FILE__, __FUNCTION__, __LINE__
          , "epoll_ctl() error(%d)", errno);
}

void udp_socket::recv(void) {
  if (_sd == -1)
    return;

  bool read_again = 1;
  while (read_again) {
    std::string data(eznetpp::opt::max_transfer_bytes, '\0');
    int len = ::recv(_sd, &data[0], eznetpp::opt::max_transfer_bytes, 0);
    read_again = 0;
    if (len == 0) {
      close();
      break;
    } else if (len == -1) {
      if (errno == EAGAIN || errno == EWOULDBLOCK)
        break;

      eznetpp::util::logger::instance().log(eznetpp::util::logger::log_level::error
          , __FILE__, __FUNCTION__, __LINE__
          , "recv() error(%d)", errno);
      close();
      break;
    }
    if (len == eznetpp::opt::max_transfer_bytes) {
      read_again = 1;
    }
    eznetpp::event::event_dispatcher::instance().push_event(
        new eznetpp::event::io_event(eznetpp::event::event_type::udp_recvfrom, len
          , errno, std::move(data), 0, this));
  }
}

void udp_socket::close(void) {
  int ret = ::close(_sd);
  _sd = -1;

  eznetpp::event::event_dispatcher::instance().push_event(
      new eznetpp::event::io_event(eznetpp::event::event_type::close, ret, errno, this));
}

int udp_socket::bind(int port) {
  struct sockaddr_in server_addr;
  bzero(&server_addr, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  server_addr.sin_port = htons(port);

  int ret = ::bind(_sd, (struct sockaddr *)&server_addr, sizeof(server_addr));

  if (ret != 0) {
    eznetpp::util::logger::instance().log(eznetpp::util::logger::log_level::error
                           , __FILE__, __FUNCTION__, __LINE__
                           , "::bind() error(%d)", errno);

    close();
    return errno;
  }

  return 0;
}

}  // namespace udp
}  // namespace net
}  // namespace eznetpp
<commit_msg>* Implement the recv function.<commit_after>//  Copyright [2015] <kangic21@gmail.com>

#include "udp_socket.h"
#include "event/event.h"
#include "event/event_dispatcher.h"

#include <cstring>

namespace eznetpp {
namespace net {
namespace udp {

udp_socket::udp_socket(void) {
  _sock_domain = socket_domain::inet_v4;
  _sock_type = socket_type::udp;

  // TODO : implement for PF_INET6
  _sd = ::socket(_sock_domain, _sock_type, 0);

  set_nonblocking();
}

udp_socket::~udp_socket(void) {
}

int udp_socket::open(int port) {
  int ret = bind(port);

  if (ret != 0)
    return ret;

  set_reuseaddr();

  return 0;
}

void udp_socket::send(void) {
  if (_sd == -1)
    return;

  {
    std::lock_guard<std::mutex> lock(_sendmsgs_mtx);
    // step 1. check the send message vector's size
    // if it isn't empty, start the loop statement to send the message.

    while (!_sendmsgs_vec.empty()) {
      // step 2. pop a message from the send message's vector
      std::string msg = _sendmsgs_vec[0].first;
      eznetpp::net::peer_addr pi = _sendmsgs_vec[0].second;
      _sendmsgs_vec.erase(_sendmsgs_vec.begin());

      // step 3. send the message and check an error case
      struct sockaddr_in client_addr;
      bzero(&client_addr, sizeof(client_addr));
      client_addr.sin_addr.s_addr = inet_addr(pi.ip.c_str());
      client_addr.sin_port = htons(pi.port);
      int ret = ::sendto(_sd, msg.c_str(), msg.length(), 0
          , (struct sockaddr *)&client_addr, sizeof(client_addr));
      if (ret == -1) {
        // error check
        if (errno == EAGAIN) {
          std::this_thread::sleep_for(std::chrono::milliseconds(1));
          continue;
        }

        break;
      }
      if (ret > 0) {
        eznetpp::event::event_dispatcher::instance().push_event(
            new eznetpp::event::io_event(eznetpp::event::event_type::udp_sendto
              , ret, errno, this));
      }
    }
  } // lock_guard

  if (set_epollout_flag(false) == -1)
      eznetpp::util::logger::instance().log(eznetpp::util::logger::log_level::error
          , __FILE__, __FUNCTION__, __LINE__
          , "epoll_ctl() error(%d)", errno);
}

void udp_socket::recv(void) {
  if (_sd == -1)
    return;

  bool read_again = 1;
  while (read_again) {
    std::string data(eznetpp::opt::max_transfer_bytes, '\0');
    struct sockaddr_in client_addr;
    socklen_t client_addr_size = sizeof(client_addr);
    bzero(&client_addr, sizeof(client_addr));
    int len = ::recvfrom(_sd, &data[0], eznetpp::opt::max_transfer_bytes, 0
        , (struct sockaddr *)&client_addr, &client_addr_size);
    read_again = 0;
    if (len == 0) {
      close();
      break;
    } else if (len == -1) {
      if (errno == EAGAIN || errno == EWOULDBLOCK)
        break;

      eznetpp::util::logger::instance().log(eznetpp::util::logger::log_level::error
          , __FILE__, __FUNCTION__, __LINE__
          , "recv() error(%d)", errno);
      close();
      break;
    }
    if (len == eznetpp::opt::max_transfer_bytes) {
      read_again = 1;
    }
    eznetpp::event::event_dispatcher::instance().push_event(
        new eznetpp::event::io_event(eznetpp::event::event_type::udp_recvfrom
          , len, errno, std::move(data), static_cast<void*>(&client_addr)
          , this));
  }
}

void udp_socket::close(void) {
  int ret = ::close(_sd);
  _sd = -1;

  eznetpp::event::event_dispatcher::instance().push_event(
      new eznetpp::event::io_event(eznetpp::event::event_type::close, ret, errno, this));
}

int udp_socket::bind(int port) {
  struct sockaddr_in server_addr;
  bzero(&server_addr, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  server_addr.sin_port = htons(port);

  int ret = ::bind(_sd, (struct sockaddr *)&server_addr, sizeof(server_addr));

  if (ret != 0) {
    eznetpp::util::logger::instance().log(eznetpp::util::logger::log_level::error
                           , __FILE__, __FUNCTION__, __LINE__
                           , "::bind() error(%d)", errno);

    close();
    return errno;
  }

  return 0;
}

}  // namespace udp
}  // namespace net
}  // namespace eznetpp
<|endoftext|>


<commit_before>/* Copyright (c) 2010 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

#include "Common.h"
#include "BackupStorage.h"

namespace RAMCloud {

// --- BackupStorage ---

/**
 * Report the read and write speed of this storage in MB/s.
 *
 * \return
 *      A pair of storage read and write speeds in MB/s.
 */
pair<uint32_t, uint32_t>
BackupStorage::benchmark()
{
    const uint64_t count = 16;
    const uint64_t mb = Segment::SEGMENT_SIZE * count / 1024 / 1024;
    uint32_t readSpeed = 0;
    uint32_t writeSpeed = 0;
    BackupStorage::Handle* handles[count];

    void* p = NULL;
    int r = posix_memalign(&p, Segment::SEGMENT_SIZE, Segment::SEGMENT_SIZE);
    if (r != 0)
        throw std::bad_alloc();
    char* segment = static_cast<char*>(p);

    try {
        for (uint64_t i = 0; i < count; ++i)
            handles[i] = NULL;
        for (uint64_t i = 0; i < count; ++i)
            handles[i] = allocate(0, i + 1);

        {
            CycleCounter<> counter;
            for (uint64_t i = 0; i < count; ++i)
                putSegment(handles[i], segment);
            uint64_t ns = cyclesToNanoseconds(counter.stop());
            writeSpeed = mb * 1000 * 1000 * 1000 / ns;
        }
        {
            CycleCounter<> counter;
            for (uint64_t i = 0; i < count; ++i)
                getSegment(handles[i], segment);
            uint64_t ns = cyclesToNanoseconds(counter.stop());
            readSpeed = mb * 1000 * 1000 * 1000 / ns;
        }
    } catch (...) {
        std::free(segment);
        for (uint64_t i = 0; i < 16; ++i)
            if (handles[i])
                free(handles[i]);
        throw;
    }

    std::free(segment);
    for (uint64_t i = 0; i < 16; ++i)
        free(handles[i]);

    LOG(NOTICE, "Backup storage speeds: %u MB/s read, %u MB/s write",
        readSpeed, writeSpeed);

    return {readSpeed, writeSpeed};
}

// --- BackupStorage::Handle ---

int32_t BackupStorage::Handle::allocatedHandlesCount = 0;

// --- SingleFileStorage ---

// - public -

/**
 * Create a SingleFileStorage.
 *
 * \param segmentSize
 *      The size in bytes of the segments this storage will deal with.
 * \param segmentFrames
 *      The number of segments this storage can store simultaneously.
 * \param filePath
 *      A filesystem path to the device or file where segments will be stored.
 * \param openFlags
 *      Extra flags for use while opening filePath (default to 0, O_DIRECT may
 *      be used to disable the OS buffer cache.
 */
SingleFileStorage::SingleFileStorage(uint32_t segmentSize,
                                     uint32_t segmentFrames,
                                     const char* filePath,
                                     int openFlags)
    : BackupStorage(segmentSize, Type::DISK)
    , freeMap(segmentFrames)
    , fd(-1)
    , killMessage()
    , killMessageLen()
    , lastAllocatedFrame(FreeMap::npos)
    , segmentFrames(segmentFrames)
{
    const char* killMessageStr = "FREE";
    killMessageLen = getpagesize();
    int r = posix_memalign(&killMessage, killMessageLen, killMessageLen);
    if (r != 0)
        throw std::bad_alloc();
    memset(killMessage, 0, killMessageLen);
    memcpy(killMessage, killMessageStr, strlen(killMessageStr));

    freeMap.set();

    fd = open(filePath,
              O_CREAT | O_RDWR | openFlags,
              0666);
    if (fd == -1)
        throw BackupStorageException(HERE,
              format("Failed to open backup storage file %s", filePath), errno);

    // If its a regular file reserve space, otherwise
    // assume its a device and we don't need to bother.
    struct stat st;
    r = stat(filePath, &st);
    if (r == -1)
        return;
    if (st.st_mode & S_IFREG)
        reserveSpace();
}

/// Close the file.
SingleFileStorage::~SingleFileStorage()
{
    int r = close(fd);
    if (r == -1)
        LOG(ERROR, "Couldn't close backup log");
    std::free(killMessage);
}

// See BackupStorage::allocate().
BackupStorage::Handle*
SingleFileStorage::allocate(uint64_t masterId,
                            uint64_t segmentId)
{
    FreeMap::size_type next = freeMap.find_next(lastAllocatedFrame);
    if (next == FreeMap::npos) {
        next = freeMap.find_first();
        if (next == FreeMap::npos)
            throw BackupStorageException(HERE, "Out of free segment frames.");
    }
    lastAllocatedFrame = next;
    uint32_t targetSegmentFrame = static_cast<uint32_t>(next);
    LOG(DEBUG, "Writing <%lu,%lu> to frame %u", masterId, segmentId,
                                                targetSegmentFrame);
    freeMap[targetSegmentFrame] = 0;
    return new Handle(targetSegmentFrame);
}

/**
 * Same as BackupStorage::benchmark() except it resets the storage to reuse
 * the segment frames that may have been used during benchmarking.
 * This allows benchmark to be called without
 * wasting early segment frames on the disk which may be faster.
 */
pair<uint32_t, uint32_t>
SingleFileStorage::benchmark()
{
    auto r = BackupStorage::benchmark();
    lastAllocatedFrame = FreeMap::npos;
    return r;
}

// See BackupStorage::free().
void
SingleFileStorage::free(BackupStorage::Handle* handle)
{
    uint32_t segmentFrame =
        static_cast<const Handle*>(handle)->getSegmentFrame();

    off_t offset = lseek(fd,
                         offsetOfSegmentFrame(segmentFrame),
                         SEEK_SET);
    if (offset == -1)
        throw BackupStorageException(HERE,
                "Failed to seek to segment frame to free storage", errno);
    ssize_t r = write(fd, killMessage, killMessageLen);
    if (r != killMessageLen)
        throw BackupStorageException(HERE,
                "Couldn't overwrite stored segment header to free", errno);

    freeMap[segmentFrame] = 1;
    delete handle;
}

// See BackupStorage::getSegment().
// NOTE: This must remain thread-safe, so be careful about adding
// access to other resources.
void
SingleFileStorage::getSegment(const BackupStorage::Handle* handle,
                              char* segment) const
{
    uint32_t sourceSegmentFrame =
        static_cast<const Handle*>(handle)->getSegmentFrame();
    off_t offset = offsetOfSegmentFrame(sourceSegmentFrame);
    ssize_t r = pread(fd, segment, segmentSize, offset);
    if (r != static_cast<ssize_t>(segmentSize))
        throw BackupStorageException(HERE, errno);
}

// See BackupStorage::putSegment().
// NOTE: This must remain thread-safe, so be careful about adding
// access to other resources.
void
SingleFileStorage::putSegment(const BackupStorage::Handle* handle,
                              const char* segment) const
{
    uint32_t targetSegmentFrame =
        static_cast<const Handle*>(handle)->getSegmentFrame();
    off_t offset = offsetOfSegmentFrame(targetSegmentFrame);
    ssize_t r = pwrite(fd, segment, segmentSize, offset);
    if (r != static_cast<ssize_t>(segmentSize))
        throw BackupStorageException(HERE, errno);
}

// - private -

/**
 * Pure function.
 *
 * \param segmentFrame
 *      The segmentFrame to find the offset of in the file.
 * \return
 *      The offset into the file a particular segmentFrame starts at.
 */
uint64_t
SingleFileStorage::offsetOfSegmentFrame(uint32_t segmentFrame) const
{
    return segmentFrame * segmentSize;
}

/**
 * Fix the size of the logfile to ensure that the OS doesn't tell us
 * the filesystem is out of space later.
 *
 * \throw BackupStorageException
 *      If space for segmentFrames segments of segmentSize cannot be reserved.
 */
void
SingleFileStorage::reserveSpace()
{
    uint64_t logSpace = segmentSize;
    logSpace *= segmentFrames;

    LOG(DEBUG, "Reserving %lu bytes of log space", logSpace);
    int r = ftruncate(fd, logSpace);
    if (r == -1)
        throw BackupStorageException(HERE,
                "Couldn't reserve storage space for backup", errno);
}

// --- InMemoryStorage ---

// - public -

/**
 * Create an in-memory storage area.
 *
 * \param segmentSize
 *      The size of segments this storage will house.
 * \param segmentFrames
 *      The number of segments this storage can house.
 */
InMemoryStorage::InMemoryStorage(uint32_t segmentSize,
                                 uint32_t segmentFrames)
    : BackupStorage(segmentSize, Type::MEMORY)
    , pool(segmentSize)
    , segmentFrames(segmentFrames)
{
}

/// Free up all storage.
InMemoryStorage::~InMemoryStorage()
{
}

// See BackupStorage::allocate().
BackupStorage::Handle*
InMemoryStorage::allocate(uint64_t masterId,
                          uint64_t segmentId)
{
    if (!segmentFrames)
        throw BackupStorageException(HERE, "Out of free segment frames.");
    segmentFrames--;
    char* address = static_cast<char *>(pool.malloc());
    return new Handle(address);
}

// See BackupStorage::free().
void
InMemoryStorage::free(BackupStorage::Handle* handle)
{
    TEST_LOG("called");
    char* address =
        static_cast<const Handle*>(handle)->getAddress();
    memcpy(address, "FREE", 4);
    pool.free(address);
    delete handle;
}

// See BackupStorage::getSegment().
// NOTE: This must remain thread-safe, so be careful about adding
// access to other resources.
void
InMemoryStorage::getSegment(const BackupStorage::Handle* handle,
                            char* segment) const
{
    char* address = static_cast<const Handle*>(handle)->getAddress();
    memcpy(segment, address, segmentSize);
}

// See BackupStorage::putSegment().
// NOTE: This must remain thread-safe, so be careful about adding
// access to other resources.
void
InMemoryStorage::putSegment(const BackupStorage::Handle* handle,
                            const char* segment) const
{
    char* address = static_cast<const Handle*>(handle)->getAddress();
    memcpy(address, segment, segmentSize);
}

} // namespace RAMCloud
<commit_msg>Write the minimum O_DIRECT requires for frees<commit_after>/* Copyright (c) 2010 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

#include "Common.h"
#include "BackupStorage.h"

namespace RAMCloud {

// --- BackupStorage ---

/**
 * Report the read and write speed of this storage in MB/s.
 *
 * \return
 *      A pair of storage read and write speeds in MB/s.
 */
pair<uint32_t, uint32_t>
BackupStorage::benchmark()
{
    const uint64_t count = 16;
    const uint64_t mb = Segment::SEGMENT_SIZE * count / 1024 / 1024;
    uint32_t readSpeed = 0;
    uint32_t writeSpeed = 0;
    BackupStorage::Handle* handles[count];

    void* p = NULL;
    int r = posix_memalign(&p, Segment::SEGMENT_SIZE, Segment::SEGMENT_SIZE);
    if (r != 0)
        throw std::bad_alloc();
    char* segment = static_cast<char*>(p);

    try {
        for (uint64_t i = 0; i < count; ++i)
            handles[i] = NULL;
        for (uint64_t i = 0; i < count; ++i)
            handles[i] = allocate(0, i + 1);

        {
            CycleCounter<> counter;
            for (uint64_t i = 0; i < count; ++i)
                putSegment(handles[i], segment);
            uint64_t ns = cyclesToNanoseconds(counter.stop());
            writeSpeed = mb * 1000 * 1000 * 1000 / ns;
        }
        {
            CycleCounter<> counter;
            for (uint64_t i = 0; i < count; ++i)
                getSegment(handles[i], segment);
            uint64_t ns = cyclesToNanoseconds(counter.stop());
            readSpeed = mb * 1000 * 1000 * 1000 / ns;
        }
    } catch (...) {
        std::free(segment);
        for (uint64_t i = 0; i < 16; ++i)
            if (handles[i])
                free(handles[i]);
        throw;
    }

    std::free(segment);
    for (uint64_t i = 0; i < 16; ++i)
        free(handles[i]);

    LOG(NOTICE, "Backup storage speeds: %u MB/s read, %u MB/s write",
        readSpeed, writeSpeed);

    return {readSpeed, writeSpeed};
}

// --- BackupStorage::Handle ---

int32_t BackupStorage::Handle::allocatedHandlesCount = 0;

// --- SingleFileStorage ---

// - public -

/**
 * Create a SingleFileStorage.
 *
 * \param segmentSize
 *      The size in bytes of the segments this storage will deal with.
 * \param segmentFrames
 *      The number of segments this storage can store simultaneously.
 * \param filePath
 *      A filesystem path to the device or file where segments will be stored.
 * \param openFlags
 *      Extra flags for use while opening filePath (default to 0, O_DIRECT may
 *      be used to disable the OS buffer cache.
 */
SingleFileStorage::SingleFileStorage(uint32_t segmentSize,
                                     uint32_t segmentFrames,
                                     const char* filePath,
                                     int openFlags)
    : BackupStorage(segmentSize, Type::DISK)
    , freeMap(segmentFrames)
    , fd(-1)
    , killMessage()
    , killMessageLen()
    , lastAllocatedFrame(FreeMap::npos)
    , segmentFrames(segmentFrames)
{
    const char* killMessageStr = "FREE";
    // Must write block size of larger when O_DIRECT.
    killMessageLen = 512;
    int r = posix_memalign(&killMessage, killMessageLen, killMessageLen);
    if (r != 0)
        throw std::bad_alloc();
    memset(killMessage, 0, killMessageLen);
    memcpy(killMessage, killMessageStr, strlen(killMessageStr));

    freeMap.set();

    fd = open(filePath,
              O_CREAT | O_RDWR | openFlags,
              0666);
    if (fd == -1)
        throw BackupStorageException(HERE,
              format("Failed to open backup storage file %s", filePath), errno);

    // If its a regular file reserve space, otherwise
    // assume its a device and we don't need to bother.
    struct stat st;
    r = stat(filePath, &st);
    if (r == -1)
        return;
    if (st.st_mode & S_IFREG)
        reserveSpace();
}

/// Close the file.
SingleFileStorage::~SingleFileStorage()
{
    int r = close(fd);
    if (r == -1)
        LOG(ERROR, "Couldn't close backup log");
    std::free(killMessage);
}

// See BackupStorage::allocate().
BackupStorage::Handle*
SingleFileStorage::allocate(uint64_t masterId,
                            uint64_t segmentId)
{
    FreeMap::size_type next = freeMap.find_next(lastAllocatedFrame);
    if (next == FreeMap::npos) {
        next = freeMap.find_first();
        if (next == FreeMap::npos)
            throw BackupStorageException(HERE, "Out of free segment frames.");
    }
    lastAllocatedFrame = next;
    uint32_t targetSegmentFrame = static_cast<uint32_t>(next);
    LOG(DEBUG, "Writing <%lu,%lu> to frame %u", masterId, segmentId,
                                                targetSegmentFrame);
    freeMap[targetSegmentFrame] = 0;
    return new Handle(targetSegmentFrame);
}

/**
 * Same as BackupStorage::benchmark() except it resets the storage to reuse
 * the segment frames that may have been used during benchmarking.
 * This allows benchmark to be called without
 * wasting early segment frames on the disk which may be faster.
 */
pair<uint32_t, uint32_t>
SingleFileStorage::benchmark()
{
    auto r = BackupStorage::benchmark();
    lastAllocatedFrame = FreeMap::npos;
    return r;
}

// See BackupStorage::free().
void
SingleFileStorage::free(BackupStorage::Handle* handle)
{
    uint32_t segmentFrame =
        static_cast<const Handle*>(handle)->getSegmentFrame();

    off_t offset = lseek(fd,
                         offsetOfSegmentFrame(segmentFrame),
                         SEEK_SET);
    if (offset == -1)
        throw BackupStorageException(HERE,
                "Failed to seek to segment frame to free storage", errno);
    ssize_t r = write(fd, killMessage, killMessageLen);
    if (r != killMessageLen)
        throw BackupStorageException(HERE,
                "Couldn't overwrite stored segment header to free", errno);

    freeMap[segmentFrame] = 1;
    delete handle;
}

// See BackupStorage::getSegment().
// NOTE: This must remain thread-safe, so be careful about adding
// access to other resources.
void
SingleFileStorage::getSegment(const BackupStorage::Handle* handle,
                              char* segment) const
{
    uint32_t sourceSegmentFrame =
        static_cast<const Handle*>(handle)->getSegmentFrame();
    off_t offset = offsetOfSegmentFrame(sourceSegmentFrame);
    ssize_t r = pread(fd, segment, segmentSize, offset);
    if (r != static_cast<ssize_t>(segmentSize))
        throw BackupStorageException(HERE, errno);
}

// See BackupStorage::putSegment().
// NOTE: This must remain thread-safe, so be careful about adding
// access to other resources.
void
SingleFileStorage::putSegment(const BackupStorage::Handle* handle,
                              const char* segment) const
{
    uint32_t targetSegmentFrame =
        static_cast<const Handle*>(handle)->getSegmentFrame();
    off_t offset = offsetOfSegmentFrame(targetSegmentFrame);
    ssize_t r = pwrite(fd, segment, segmentSize, offset);
    if (r != static_cast<ssize_t>(segmentSize))
        throw BackupStorageException(HERE, errno);
}

// - private -

/**
 * Pure function.
 *
 * \param segmentFrame
 *      The segmentFrame to find the offset of in the file.
 * \return
 *      The offset into the file a particular segmentFrame starts at.
 */
uint64_t
SingleFileStorage::offsetOfSegmentFrame(uint32_t segmentFrame) const
{
    return segmentFrame * segmentSize;
}

/**
 * Fix the size of the logfile to ensure that the OS doesn't tell us
 * the filesystem is out of space later.
 *
 * \throw BackupStorageException
 *      If space for segmentFrames segments of segmentSize cannot be reserved.
 */
void
SingleFileStorage::reserveSpace()
{
    uint64_t logSpace = segmentSize;
    logSpace *= segmentFrames;

    LOG(DEBUG, "Reserving %lu bytes of log space", logSpace);
    int r = ftruncate(fd, logSpace);
    if (r == -1)
        throw BackupStorageException(HERE,
                "Couldn't reserve storage space for backup", errno);
}

// --- InMemoryStorage ---

// - public -

/**
 * Create an in-memory storage area.
 *
 * \param segmentSize
 *      The size of segments this storage will house.
 * \param segmentFrames
 *      The number of segments this storage can house.
 */
InMemoryStorage::InMemoryStorage(uint32_t segmentSize,
                                 uint32_t segmentFrames)
    : BackupStorage(segmentSize, Type::MEMORY)
    , pool(segmentSize)
    , segmentFrames(segmentFrames)
{
}

/// Free up all storage.
InMemoryStorage::~InMemoryStorage()
{
}

// See BackupStorage::allocate().
BackupStorage::Handle*
InMemoryStorage::allocate(uint64_t masterId,
                          uint64_t segmentId)
{
    if (!segmentFrames)
        throw BackupStorageException(HERE, "Out of free segment frames.");
    segmentFrames--;
    char* address = static_cast<char *>(pool.malloc());
    return new Handle(address);
}

// See BackupStorage::free().
void
InMemoryStorage::free(BackupStorage::Handle* handle)
{
    TEST_LOG("called");
    char* address =
        static_cast<const Handle*>(handle)->getAddress();
    memcpy(address, "FREE", 4);
    pool.free(address);
    delete handle;
}

// See BackupStorage::getSegment().
// NOTE: This must remain thread-safe, so be careful about adding
// access to other resources.
void
InMemoryStorage::getSegment(const BackupStorage::Handle* handle,
                            char* segment) const
{
    char* address = static_cast<const Handle*>(handle)->getAddress();
    memcpy(segment, address, segmentSize);
}

// See BackupStorage::putSegment().
// NOTE: This must remain thread-safe, so be careful about adding
// access to other resources.
void
InMemoryStorage::putSegment(const BackupStorage::Handle* handle,
                            const char* segment) const
{
    char* address = static_cast<const Handle*>(handle)->getAddress();
    memcpy(address, segment, segmentSize);
}

} // namespace RAMCloud
<|endoftext|>


<commit_before>#include <node.h>
#include <initializer_list>
#include <tuple>

#include "Pump.h"
#include "calculator/PumpEfficiency.h"
#include "calculator/OptimalPumpEfficiency.h"
#include "calculator/MotorRatedPower.h"
#include "calculator/OptimalMotorRatedPower.h"
#include "calculator/MotorShaftPower.h"
#include "calculator/OptimalMotorShaftPower.h"
#include "calculator/PumpShaftPower.h"
#include "calculator/OptimalPumpShaftPower.h"
#include "calculator/MotorEfficiency.h"
#include "calculator/OptimalMotorEfficiency.h"
#include "calculator/MotorPowerFactor.h"
#include "calculator/OptimalMotorPowerFactor.h"
#include "calculator/MotorCurrent.h"
#include "calculator/OptimalMotorCurrent.h"
#include "calculator/MotorPower.h"
#include "calculator/OptimalMotorPower.h"
#include "AnnualEnergy.h"
#include "AnnualCost.h"
#include "AnnualSavingsPotential.h"
#include "OptimizationRating.h"

using namespace v8;

Isolate* iso;
Local<Object> inp;

double Get(const char *nm) {
  return inp->ToObject()->Get(String::NewFromUtf8(iso,nm))->NumberValue();
}
void Results(const FunctionCallbackInfo<Value>& args) {
  iso = args.GetIsolate();
  inp = args[0]->ToObject();
  auto r = Object::New(iso);

  auto drive = static_cast<Pump::Drive>(Get("drive"));
  auto effCls = static_cast<Motor::EfficiencyClass>(Get("efficiency_class"));

  auto loadMeth = FieldData::LoadEstimationMethod::POWER;
  double mp = Get("motor_field_power");
  double mc = Get("motor_field_current");
  if (mc>0) {
    loadMeth = FieldData::LoadEstimationMethod::CURRENT;
    mp = (new MotorPower(Get("motor_rated_voltage"),mc,0))->calculate();//power factor
  } else {
    mc = (new MotorCurrent(Get("motor_rated_power"),Get("motor_rated_speed"),effCls,0))->calculate();//loadf
  }
  auto msp = (new MotorShaftPower(Get("motor_rated_power"),mp,Get("motor_rated_speed"),effCls,Get("motor_rated_voltage")));

  std::initializer_list <std::tuple<const char *,double,double>> out = {
    {"Motor Shaft Power",msp->calculate(),0},
    {"Motor Current",msp->calculateCurrent(),0},
    {"Motor Efficiency",msp->calculateEfficiency(),0},
    {"Motor Power Factor",msp->calculateElectricPower(),0},
    {"Motor Power", msp->calculateElectricPower(),0}
  };

  for(auto p: out) {
    auto a = Array::New(iso);
    a->Set(0,Number::New(iso,std::get<1>(p)));
    a->Set(1,Number::New(iso,std::get<2>(p)));
    r->Set(String::NewFromUtf8(iso,std::get<0>(p)),a);
  }
  // SetR({
  //   0,//(new PumpEfficiency(Get("specific_gravity"),Get("flow"),Get("head"),0))->calculate(),//pumpShaftPower
  //   0,//(new OptimalPumpEfficiency(static_cast<Pump::Style>(Get("style")),
  //     //Get("pump_rated_speed"),Get("viscosity"),Get("stages"),Get("flow"),Get("head"),static_cast<Pump::Speed>(!Get("speed"))))->calculate(),
  //   0,//mp,
  //   0,//(new OptimalMotorRatedPower(0,Get("margin")))->calculate(),//motorshaftpower
  //   (new MotorShaftPower(Get("motor_rated_power"),mp,Get("motor_rated_speed"),effCls,Get("motor_rated_voltage")))->calculate(),
  //   0,//(new OptimalMotorShaftPower(0,drive))->calculate(),//pumpshaftpower
  //   0,//(new PumpShaftPower(0,drive))->calculate(),//motorshaftpower
  //   0,//(new OptimalPumpShaftPower(Get("flow"),Get("head"),Get("specific_gravity"),0))->calculate(),//pumpeff
  //   0,//(new MotorEfficiency(Get("motor_rated_speed"),effCls,Get("motor_rated_power"),mp,0))->calculate(),//loadF
  //   0,//(new OptimalMotorEfficiency(Get("motor_rated_power"),0))->calculate(),//motor shaft power
  //   0,//(new MotorPowerFactor(Get("motor_rated_power"),0,mc,0,Get("motor_rated_voltage")))->calculate(),//loadFactor??, motor eff
  //   0,//(new OptimalMotorPowerFactor(Get("motor_rated_power"),0))->calculate(),//opt motor power?
  //   0,//mc,
  //   0,//(new OptimalMotorCurrent(0,Get("field_voltage")))->calculate(),//opt motor power
  //   0,//mp,
  //   0,//(new OptimalMotorPower(0,0))->calculate(),//motorshaftpower, motor eff
  //   0,//(new AnnualEnergy(mp,Get("fraction")))->calculate(),//motorpower
  //   0,//(new AnnualEnergy(0,Get("fraction")))->calculate(),//opt motorpower
  //   0,//(new AnnualCost(0,Get("cost")))->calculate(),//ex ann energy
  //   0,//(new AnnualCost(0,Get("cost")))->calculate(),//opt ann energy
  //   -1,
  //   0,//(new AnnualSavingsPotential(0,0))->calculate(),//ex an cost, opt an cost
  //   -1,
  //   0,//(new OptimizationRating(0,0))->calculate()//ex an cost, opt an cost
  // });
  args.GetReturnValue().Set(r);
}
void EstFLA(const FunctionCallbackInfo<Value>& args) {
  args[0]->NumberValue();//hp
  args[1]->NumberValue();//speed
  args[2]->NumberValue();//v
  args[3]->NumberValue();//cls
  args[4]->NumberValue();//cus cls
  args.GetReturnValue().Set(args[4]);
}
void Init(Local<Object> exports) {
  NODE_SET_METHOD(exports, "results", Results);
  NODE_SET_METHOD(exports, "estFLA", EstFLA);
}

NODE_MODULE(bridge, Init)

<commit_msg>no message<commit_after>#include <node.h>
#include <initializer_list>
#include <tuple>

#include "Pump.h"
#include "calculator/PumpEfficiency.h"
#include "calculator/OptimalPumpEfficiency.h"
#include "calculator/MotorRatedPower.h"
#include "calculator/OptimalMotorRatedPower.h"
#include "calculator/MotorShaftPower.h"
#include "calculator/OptimalMotorShaftPower.h"
#include "calculator/PumpShaftPower.h"
#include "calculator/OptimalPumpShaftPower.h"
#include "calculator/MotorEfficiency.h"
#include "calculator/OptimalMotorEfficiency.h"
#include "calculator/MotorPowerFactor.h"
#include "calculator/OptimalMotorPowerFactor.h"
#include "calculator/MotorCurrent.h"
#include "calculator/OptimalMotorCurrent.h"
#include "calculator/MotorPower.h"
#include "calculator/OptimalMotorPower.h"
#include "AnnualEnergy.h"
#include "AnnualCost.h"
#include "AnnualSavingsPotential.h"
#include "OptimizationRating.h"

using namespace v8;

Isolate* iso;
Local<Object> inp;

double Get(const char *nm) {
  return inp->ToObject()->Get(String::NewFromUtf8(iso,nm))->NumberValue();
}
void Results(const FunctionCallbackInfo<Value>& args) {
  iso = args.GetIsolate();
  inp = args[0]->ToObject();
  auto r = Object::New(iso);

  auto i4 = Get("efficiency_class");
  auto drive = static_cast<Pump::Drive>(Get("drive"));
  auto effCls = static_cast<Motor::EfficiencyClass>(i4);

  auto loadMeth = FieldData::LoadEstimationMethod::POWER;
  double mp = Get("motor_field_power");
  double mc = Get("motor_field_current");
  if (mc>0) {
    loadMeth = FieldData::LoadEstimationMethod::CURRENT;
    mp = (new MotorPower(Get("motor_rated_voltage"),mc,0))->calculate();//power factor
  } else {
    mc = (new MotorCurrent(Get("motor_rated_power"),Get("motor_rated_speed"),effCls,0))->calculate();//loadf
  }
  auto i1 = Get("motor_rated_power"), i2 = mp, i3 = Get("motor_rated_speed"), i5 = Get("motor_rated_voltage");

  auto msp = (new MotorShaftPower(i1,i2,i3,effCls,i5));

  std::initializer_list <std::tuple<const char *,double,double>> out = {
    {"Motor Shaft Power",msp->calculate(),0},
    {"Motor Current",msp->calculateCurrent(),0},
    {"Motor Efficiency",msp->calculateEfficiency(),0},
    {"Motor Power Factor",msp->calculateElectricPower(),0},
    {"Motor Power", msp->calculateElectricPower(),0},
    {"i1",i1,0},
    {"i2",i2,0},
    {"i3",i3,0},
    {"i4",i4,0},
    {"o1",msp->calculate(),0}

  };
  // std::initializer_list <std::tuple<const char *,double,double>> out = {
  //   {"Motor Shaft Power",3,0},
  //   {"Motor Current",2,0},
  //   {"Motor Efficiency",6,0},
  //   {"Motor Power Factor",45,0},
  //   {"Motor Power", 9,0}
  // };
  for(auto p: out) {
    auto a = Array::New(iso);
    a->Set(0,Number::New(iso,std::get<1>(p)));
    a->Set(1,Number::New(iso,std::get<2>(p)));
    r->Set(String::NewFromUtf8(iso,std::get<0>(p)),a);
  }
  // SetR({
  //   0,//(new PumpEfficiency(Get("specific_gravity"),Get("flow"),Get("head"),0))->calculate(),//pumpShaftPower
  //   0,//(new OptimalPumpEfficiency(static_cast<Pump::Style>(Get("style")),
  //     //Get("pump_rated_speed"),Get("viscosity"),Get("stages"),Get("flow"),Get("head"),static_cast<Pump::Speed>(!Get("speed"))))->calculate(),
  //   0,//mp,
  //   0,//(new OptimalMotorRatedPower(0,Get("margin")))->calculate(),//motorshaftpower
  //   (new MotorShaftPower(Get("motor_rated_power"),mp,Get("motor_rated_speed"),effCls,Get("motor_rated_voltage")))->calculate(),
  //   0,//(new OptimalMotorShaftPower(0,drive))->calculate(),//pumpshaftpower
  //   0,//(new PumpShaftPower(0,drive))->calculate(),//motorshaftpower
  //   0,//(new OptimalPumpShaftPower(Get("flow"),Get("head"),Get("specific_gravity"),0))->calculate(),//pumpeff
  //   0,//(new MotorEfficiency(Get("motor_rated_speed"),effCls,Get("motor_rated_power"),mp,0))->calculate(),//loadF
  //   0,//(new OptimalMotorEfficiency(Get("motor_rated_power"),0))->calculate(),//motor shaft power
  //   0,//(new MotorPowerFactor(Get("motor_rated_power"),0,mc,0,Get("motor_rated_voltage")))->calculate(),//loadFactor??, motor eff
  //   0,//(new OptimalMotorPowerFactor(Get("motor_rated_power"),0))->calculate(),//opt motor power?
  //   0,//mc,
  //   0,//(new OptimalMotorCurrent(0,Get("field_voltage")))->calculate(),//opt motor power
  //   0,//mp,
  //   0,//(new OptimalMotorPower(0,0))->calculate(),//motorshaftpower, motor eff
  //   0,//(new AnnualEnergy(mp,Get("fraction")))->calculate(),//motorpower
  //   0,//(new AnnualEnergy(0,Get("fraction")))->calculate(),//opt motorpower
  //   0,//(new AnnualCost(0,Get("cost")))->calculate(),//ex ann energy
  //   0,//(new AnnualCost(0,Get("cost")))->calculate(),//opt ann energy
  //   -1,
  //   0,//(new AnnualSavingsPotential(0,0))->calculate(),//ex an cost, opt an cost
  //   -1,
  //   0,//(new OptimizationRating(0,0))->calculate()//ex an cost, opt an cost
  // });
  args.GetReturnValue().Set(r);
}
void EstFLA(const FunctionCallbackInfo<Value>& args) {
  args[0]->NumberValue();//hp
  args[1]->NumberValue();//speed
  args[2]->NumberValue();//v
  args[3]->NumberValue();//cls
  args[4]->NumberValue();//cus cls
  args.GetReturnValue().Set(args[4]);
}
void Init(Local<Object> exports) {
  NODE_SET_METHOD(exports, "results", Results);
  NODE_SET_METHOD(exports, "estFLA", EstFLA);
}

NODE_MODULE(bridge, Init)

<|endoftext|>


<commit_before>#include <node.h>
#include <initializer_list>
#include <tuple>
#include <iostream>
#include <fstream>

#include "Pump.h"
#include "calculator/PumpEfficiency.h"
#include "calculator/OptimalPumpEfficiency.h"
#include "calculator/MotorRatedPower.h"
#include "calculator/OptimalMotorRatedPower.h"
#include "calculator/MotorShaftPower.h"
#include "calculator/OptimalMotorShaftPower.h"
#include "calculator/PumpShaftPower.h"
#include "calculator/OptimalPumpShaftPower.h"
#include "calculator/MotorEfficiency.h"
#include "calculator/OptimalMotorEfficiency.h"
#include "calculator/MotorPowerFactor.h"
#include "calculator/OptimalMotorPowerFactor.h"
#include "calculator/MotorCurrent.h"
#include "calculator/OptimalMotorCurrent.h"
#include "calculator/MotorPower.h"
#include "calculator/OptimalMotorPower.h"
#include "AnnualEnergy.h"
#include "AnnualCost.h"
#include "AnnualSavingsPotential.h"
#include "OptimizationRating.h"

using namespace v8;
using namespace std;

Isolate* iso;
Local<Object> inp;

double Get(const char *nm) {
  return inp->ToObject()->Get(String::NewFromUtf8(iso,nm))->NumberValue();
}
void Results(const FunctionCallbackInfo<Value>& args) {
  iso = args.GetIsolate();
  inp = args[1]->ToObject();
  auto r = Object::New(iso);

  auto drive = static_cast<Pump::Drive>((int)Get("drive"));
  auto effCls = static_cast<Motor::EfficiencyClass>((int)Get("efficiency_class"));

  auto loadMeth = FieldData::LoadEstimationMethod::POWER;
  double mp = Get("motor_field_power");
  double mc = Get("motor_field_current");
  if (mc>0) {
    loadMeth = FieldData::LoadEstimationMethod::CURRENT;
    mp = (new MotorPower(Get("motor_rated_voltage"),mc,0))->calculate();//power factor
  } else {
    mc = (new MotorCurrent(Get("motor_rated_power"),Get("motor_rated_speed"),effCls,0))->calculate();//loadf
  }

  auto msp = (new MotorShaftPower(Get("motor_rated_power"),mp,Get("motor_rated_speed"),effCls,Get("motor_rated_voltage")));

  std::initializer_list <tuple<const char *,double,double>> out = {
    {"Motor Shaft Power",msp->calculate(),0},
    {"Motor Current",msp->calculateCurrent(),0},
    {"Motor Efficiency",msp->calculateEfficiency(),0},
    {"Motor Power Factor",msp->calculateElectricPower(),0},
    {"Motor Power", msp->calculateElectricPower(),0}
  };
  for(auto p: out) {
    auto a = Array::New(iso);
    a->Set(0,Number::New(iso,get<1>(p)));
    a->Set(1,Number::New(iso,get<2>(p)));
    r->Set(String::NewFromUtf8(iso,get<0>(p)),a);
  }
  // SetR({
  //   0,//(new PumpEfficiency(Get("specific_gravity"),Get("flow"),Get("head"),0))->calculate(),//pumpShaftPower
  //   0,//(new OptimalPumpEfficiency(static_cast<Pump::Style>(Get("style")),
  //     //Get("pump_rated_speed"),Get("viscosity"),Get("stages"),Get("flow"),Get("head"),static_cast<Pump::Speed>(!Get("speed"))))->calculate(),
  //   0,//mp,
  //   0,//(new OptimalMotorRatedPower(0,Get("margin")))->calculate(),//motorshaftpower
  //   (new MotorShaftPower(Get("motor_rated_power"),mp,Get("motor_rated_speed"),effCls,Get("motor_rated_voltage")))->calculate(),
  //   0,//(new OptimalMotorShaftPower(0,drive))->calculate(),//pumpshaftpower
  //   0,//(new PumpShaftPower(0,drive))->calculate(),//motorshaftpower
  //   0,//(new OptimalPumpShaftPower(Get("flow"),Get("head"),Get("specific_gravity"),0))->calculate(),//pumpeff
  //   0,//(new MotorEfficiency(Get("motor_rated_speed"),effCls,Get("motor_rated_power"),mp,0))->calculate(),//loadF
  //   0,//(new OptimalMotorEfficiency(Get("motor_rated_power"),0))->calculate(),//motor shaft power
  //   0,//(new MotorPowerFactor(Get("motor_rated_power"),0,mc,0,Get("motor_rated_voltage")))->calculate(),//loadFactor??, motor eff
  //   0,//(new OptimalMotorPowerFactor(Get("motor_rated_power"),0))->calculate(),//opt motor power?
  //   0,//mc,
  //   0,//(new OptimalMotorCurrent(0,Get("field_voltage")))->calculate(),//opt motor power
  //   0,//mp,
  //   0,//(new OptimalMotorPower(0,0))->calculate(),//motorshaftpower, motor eff
  //   0,//(new AnnualEnergy(mp,Get("fraction")))->calculate(),//motorpower
  //   0,//(new AnnualEnergy(0,Get("fraction")))->calculate(),//opt motorpower
  //   0,//(new AnnualCost(0,Get("cost")))->calculate(),//ex ann energy
  //   0,//(new AnnualCost(0,Get("cost")))->calculate(),//opt ann energy
  //   -1,
  //   0,//(new AnnualSavingsPotential(0,0))->calculate(),//ex an cost, opt an cost
  //   -1,
  //   0,//(new OptimizationRating(0,0))->calculate()//ex an cost, opt an cost
  // });
  args.GetReturnValue().Set(r);
}
void EstFLA(const FunctionCallbackInfo<Value>& args) {
  args[0]->NumberValue();//hp
  args[1]->NumberValue();//speed
  args[2]->NumberValue();//v
  args[3]->NumberValue();//cls
  args[4]->NumberValue();//cus cls
  args.GetReturnValue().Set(args[4]);
}
ofstream Out;
void Check(double exp, double act) {
  Out << "Expected:" << exp << "; Actual: " << act << "; " <<
    (roundf(act*100)/100 == roundf(exp*100)/100 ? "PASS" : "*** FAIL ***") << endl;
}
void TestBasic() {
  Out.open ("clog.txt");
  Out << "MotorShaftPower(200,80,1786,Motor::EfficiencyClass::ENERGY_EFFICIENT,460)" << endl;
  auto msp = (new MotorShaftPower(200,80,1786,Motor::EfficiencyClass::ENERGY_EFFICIENT,460));
  Check(101.25,msp->calculate());
}
void TestSame() {
  Out << "MotorShaftPower(200,80,1786,Motor::EfficiencyClass::ENERGY_EFFICIENT,460)" << endl;
  auto msp = (new MotorShaftPower(200,80,1786,Motor::EfficiencyClass::ENERGY_EFFICIENT,460));

  for (int i=1; i<=25; i=i+2) {
    Out << "**** " << i << " ******" << endl;
    Check(msp->calculate(),msp->calculate());
  }
}
void Test(const FunctionCallbackInfo<Value>& args) {
  Out.open ("clog.txt");
  TestSame();
  Out.close();
}
void Init(Local<Object> exports) {
  NODE_SET_METHOD(exports, "results", Results);
  NODE_SET_METHOD(exports, "estFLA", EstFLA);
  NODE_SET_METHOD(exports, "test", Test);
}

NODE_MODULE(bridge, Init)

<commit_msg>no message<commit_after>#include <node.h>
#include <initializer_list>
#include <tuple>
#include <iostream>
#include <fstream>

#include "Pump.h"
#include "calculator/PumpEfficiency.h"
#include "calculator/OptimalPumpEfficiency.h"
#include "calculator/MotorRatedPower.h"
#include "calculator/OptimalMotorRatedPower.h"
#include "calculator/MotorShaftPower.h"
#include "calculator/OptimalMotorShaftPower.h"
#include "calculator/PumpShaftPower.h"
#include "calculator/OptimalPumpShaftPower.h"
#include "calculator/MotorEfficiency.h"
#include "calculator/OptimalMotorEfficiency.h"
#include "calculator/MotorPowerFactor.h"
#include "calculator/OptimalMotorPowerFactor.h"
#include "calculator/MotorCurrent.h"
#include "calculator/OptimalMotorCurrent.h"
#include "calculator/MotorPower.h"
#include "calculator/OptimalMotorPower.h"
#include "AnnualEnergy.h"
#include "AnnualCost.h"
#include "AnnualSavingsPotential.h"
#include "OptimizationRating.h"

using namespace v8;
using namespace std;

Isolate* iso;
Local<Object> inp;

double Get(const char *nm) {
  return inp->ToObject()->Get(String::NewFromUtf8(iso,nm))->NumberValue();
}
void Results(const FunctionCallbackInfo<Value>& args) {
  iso = args.GetIsolate();
  inp = args[1]->ToObject();
  auto r = Object::New(iso);

  auto drive = (Pump::Drive)((int)Get("drive"));
  auto effCls = (Motor::EfficiencyClass)((int)Get("efficiency_class"));

  auto loadMeth = FieldData::LoadEstimationMethod::POWER;
  double mp = Get("motor_field_power");
  double mc = Get("motor_field_current");
  if (mc>0) {
    loadMeth = FieldData::LoadEstimationMethod::CURRENT;
    mp = (new MotorPower(Get("motor_rated_voltage"),mc,0))->calculate();//power factor
  } else {
    mc = (new MotorCurrent(Get("motor_rated_power"),Get("motor_rated_speed"),effCls,0))->calculate();//loadf
  }

  auto msp = (new MotorShaftPower(Get("motor_rated_power"),mp,Get("motor_rated_speed"),effCls,Get("motor_rated_voltage")));

  std::initializer_list <tuple<const char *,double,double>> out = {
    {"Motor Shaft Power",msp->calculate(),0},
    {"Motor Current",msp->calculateCurrent(),0},
    {"Motor Efficiency",msp->calculateEfficiency(),0},
    {"Motor Power Factor",msp->calculateElectricPower(),0},
    {"Motor Power", msp->calculateElectricPower(),0}
  };
  for(auto p: out) {
    auto a = Array::New(iso);
    a->Set(0,Number::New(iso,get<1>(p)));
    a->Set(1,Number::New(iso,get<2>(p)));
    r->Set(String::NewFromUtf8(iso,get<0>(p)),a);
  }
  // SetR({
  //   0,//(new PumpEfficiency(Get("specific_gravity"),Get("flow"),Get("head"),0))->calculate(),//pumpShaftPower
  //   0,//(new OptimalPumpEfficiency(static_cast<Pump::Style>(Get("style")),
  //     //Get("pump_rated_speed"),Get("viscosity"),Get("stages"),Get("flow"),Get("head"),static_cast<Pump::Speed>(!Get("speed"))))->calculate(),
  //   0,//mp,
  //   0,//(new OptimalMotorRatedPower(0,Get("margin")))->calculate(),//motorshaftpower
  //   (new MotorShaftPower(Get("motor_rated_power"),mp,Get("motor_rated_speed"),effCls,Get("motor_rated_voltage")))->calculate(),
  //   0,//(new OptimalMotorShaftPower(0,drive))->calculate(),//pumpshaftpower
  //   0,//(new PumpShaftPower(0,drive))->calculate(),//motorshaftpower
  //   0,//(new OptimalPumpShaftPower(Get("flow"),Get("head"),Get("specific_gravity"),0))->calculate(),//pumpeff
  //   0,//(new MotorEfficiency(Get("motor_rated_speed"),effCls,Get("motor_rated_power"),mp,0))->calculate(),//loadF
  //   0,//(new OptimalMotorEfficiency(Get("motor_rated_power"),0))->calculate(),//motor shaft power
  //   0,//(new MotorPowerFactor(Get("motor_rated_power"),0,mc,0,Get("motor_rated_voltage")))->calculate(),//loadFactor??, motor eff
  //   0,//(new OptimalMotorPowerFactor(Get("motor_rated_power"),0))->calculate(),//opt motor power?
  //   0,//mc,
  //   0,//(new OptimalMotorCurrent(0,Get("field_voltage")))->calculate(),//opt motor power
  //   0,//mp,
  //   0,//(new OptimalMotorPower(0,0))->calculate(),//motorshaftpower, motor eff
  //   0,//(new AnnualEnergy(mp,Get("fraction")))->calculate(),//motorpower
  //   0,//(new AnnualEnergy(0,Get("fraction")))->calculate(),//opt motorpower
  //   0,//(new AnnualCost(0,Get("cost")))->calculate(),//ex ann energy
  //   0,//(new AnnualCost(0,Get("cost")))->calculate(),//opt ann energy
  //   -1,
  //   0,//(new AnnualSavingsPotential(0,0))->calculate(),//ex an cost, opt an cost
  //   -1,
  //   0,//(new OptimizationRating(0,0))->calculate()//ex an cost, opt an cost
  // });
  args.GetReturnValue().Set(r);
}
void EstFLA(const FunctionCallbackInfo<Value>& args) {
  args[0]->NumberValue();//hp
  args[1]->NumberValue();//speed
  args[2]->NumberValue();//v
  args[3]->NumberValue();//cls
  args[4]->NumberValue();//cus cls
  args.GetReturnValue().Set(args[4]);
}
ofstream Out;
void Check(double exp, double act) {
  Out << "Expected:" << exp << "; Actual: " << act << "; " <<
    (roundf(act*100)/100 == roundf(exp*100)/100 ? "PASS" : "*** FAIL ***") << endl;
}
void TestBasic() {
  Out.open ("clog.txt");
  Out << "MotorShaftPower(200,80,1786,Motor::EfficiencyClass::ENERGY_EFFICIENT,460)" << endl;
  auto msp = (new MotorShaftPower(200,80,1786,Motor::EfficiencyClass::ENERGY_EFFICIENT,460));
  Check(101.25,msp->calculate());
}
void TestSame() {
  Out << "MotorShaftPower(200,80,1786,Motor::EfficiencyClass::ENERGY_EFFICIENT,460)" << endl;
  auto msp = (new MotorShaftPower(200,80,1786,Motor::EfficiencyClass::ENERGY_EFFICIENT,460));

  for (int i=1; i<=25; i=i+2) {
    Out << "**** " << i << " ******" << endl;
    Check(msp->calculate(),msp->calculate());
  }
}
void Test(const FunctionCallbackInfo<Value>& args) {
  Out.open ("clog.txt");
  TestSame();
  Out.close();
}
void Init(Local<Object> exports) {
  NODE_SET_METHOD(exports, "results", Results);
  NODE_SET_METHOD(exports, "estFLA", EstFLA);
  NODE_SET_METHOD(exports, "test", Test);
}

NODE_MODULE(bridge, Init)

<|endoftext|>


<commit_before>#include <node.h>
#include <initializer_list>

#include "../amo-library/Pump.h"
#include "../amo-library/calculator/PumpEfficiency.h"
#include "../amo-library/calculator/OptimalPumpEfficiency.h"
#include "../amo-library/calculator/MotorRatedPower.h"
#include "../amo-library/calculator/OptimalMotorRatedPower.h"
#include "../amo-library/calculator/MotorShaftPower.h"
#include "../amo-library/calculator/OptimalMotorShaftPower.h"
#include "../amo-library/calculator/PumpShaftPower.h"
#include "../amo-library/calculator/OptimalPumpShaftPower.h"
#include "../amo-library/calculator/MotorEfficiency.h"
#include "../amo-library/calculator/OptimalMotorEfficiency.h"
#include "../amo-library/calculator/MotorPowerFactor.h"
#include "../amo-library/calculator/OptimalMotorPowerFactor.h"
#include "../amo-library/calculator/MotorCurrent.h"
#include "../amo-library/calculator/OptimalMotorCurrent.h"
#include "../amo-library/calculator/MotorPower.h"
#include "../amo-library/calculator/OptimalMotorPower.h"
#include "../amo-library/AnnualEnergy.h"
#include "../amo-library/AnnualCost.h"
#include "../amo-library/AnnualSavingsPotential.h"
#include "../amo-library/OptimizationRating.h"

using namespace v8;

Local<Array> r;
Isolate* iso;
Local<Object> inp;

void set(std::initializer_list <double> args) {
  for (auto d : args) {
    r->Set(r->Length(),Number::New(iso,d));
  }
}
double get(const char * nm) {
  return inp->ToObject()->Get(String::NewFromUtf8(iso,nm))->NumberValue();
}
void Results(const FunctionCallbackInfo<Value>& args) {
  iso = args.GetIsolate();
  r = Array::New(iso);
  inp = args[0]->ToObject();
  set({
    (new PumpEfficiency(get("specific_gravity"),get("flow"),get("head"),get("power_rating")))->calculate(),
    (new OptimalPumpEfficiency(Pump::Style::END_SUCTION_SLURRY,get("pump_rpm"),get("viscosity"),get("stages"),get("flow"),get("head"),Pump::Speed::FIXED_SPECIFIC_SPEED))->calculate(),
    (new MotorRatedPower(0))->calculate(),
    (new OptimalMotorRatedPower(0,0))->calculate(),
    (new MotorShaftPower(0,0))->calculate(),
    (new OptimalMotorShaftPower(0,Pump::Drive::DIRECT_DRIVE))->calculate(),
    (new PumpShaftPower(0,Pump::Drive::DIRECT_DRIVE))->calculate(),
    (new OptimalPumpShaftPower(0,0,0,0))->calculate(),
    (new MotorEfficiency(0,0,Motor::EfficiencyClass::STANDARD,0,FieldData::LoadEstimationMethod::POWER,0,0,0))->calculate(),
    (new OptimalMotorEfficiency(0,0))->calculate(),
    (new MotorPowerFactor(0,0,Motor::EfficiencyClass::STANDARD,0,FieldData::LoadEstimationMethod::POWER,0,0,0))->calculate(),
    (new OptimalMotorPowerFactor(0,0))->calculate(),
    (new MotorCurrent(0,0,0))->calculate(),
    (new OptimalMotorCurrent(0,0))->calculate(),
    (new MotorPower(0,0,0,0))->calculate(),
    (new OptimalMotorPower(0,0))->calculate(),
    (new AnnualEnergy(0,0))->calculate(),
    (new AnnualEnergy(0,0))->calculate(),
    (new AnnualCost(0,0))->calculate(),
    (new AnnualCost(0,0))->calculate(),
    -1,
    (new AnnualSavingsPotential(0,0))->calculate(),
    -1,
    (new OptimizationRating(0,0))->calculate()
  });
  args.GetReturnValue().Set(r);
}

void init(Local<Object> exports) {
  NODE_SET_METHOD(exports, "results", Results);
}

NODE_MODULE(bridge, init)

<commit_msg>no message<commit_after>#include <node.h>
#include <initializer_list>

#include "../amo-library/Pump.h"
#include "../amo-library/calculator/PumpEfficiency.h"
#include "../amo-library/calculator/OptimalPumpEfficiency.h"
#include "../amo-library/calculator/MotorRatedPower.h"
#include "../amo-library/calculator/OptimalMotorRatedPower.h"
#include "../amo-library/calculator/MotorShaftPower.h"
#include "../amo-library/calculator/OptimalMotorShaftPower.h"
#include "../amo-library/calculator/PumpShaftPower.h"
#include "../amo-library/calculator/OptimalPumpShaftPower.h"
#include "../amo-library/calculator/MotorEfficiency.h"
#include "../amo-library/calculator/OptimalMotorEfficiency.h"
#include "../amo-library/calculator/MotorPowerFactor.h"
#include "../amo-library/calculator/OptimalMotorPowerFactor.h"
#include "../amo-library/calculator/MotorCurrent.h"
#include "../amo-library/calculator/OptimalMotorCurrent.h"
#include "../amo-library/calculator/MotorPower.h"
#include "../amo-library/calculator/OptimalMotorPower.h"
#include "../amo-library/AnnualEnergy.h"
#include "../amo-library/AnnualCost.h"
#include "../amo-library/AnnualSavingsPotential.h"
#include "../amo-library/OptimizationRating.h"

using namespace v8;

Local<Array> r;
Isolate* iso;
Local<Object> inp;

void set(std::initializer_list <double> args) {
  for (auto d : args) {
    r->Set(r->Length(),Number::New(iso,d));
  }
}
double get(const char * nm) {
  return inp->ToObject()->Get(String::NewFromUtf8(iso,nm))->NumberValue();
}
void Results(const FunctionCallbackInfo<Value>& args) {
  iso = args.GetIsolate();
  r = Array::New(iso);
  inp = args[0]->ToObject();
  set({
    (new PumpEfficiency(get("specific_gravity"),get("flow"),get("head"),get("power_rating")))->calculate(),
    (new OptimalPumpEfficiency(static_cast<Pump::Style>(get("style")),get("pump_rpm"),get("viscosity"),get("stages"),get("flow"),get("head"),static_cast<Pump::Speed>(!get("speed"))))->calculate(),
    (new MotorRatedPower(0))->calculate(),
    (new OptimalMotorRatedPower(0,0))->calculate(),
    (new MotorShaftPower(0,0))->calculate(),
    (new OptimalMotorShaftPower(0,Pump::Drive::DIRECT_DRIVE))->calculate(),
    (new PumpShaftPower(0,Pump::Drive::DIRECT_DRIVE))->calculate(),
    (new OptimalPumpShaftPower(0,0,0,0))->calculate(),
    (new MotorEfficiency(0,0,Motor::EfficiencyClass::STANDARD,0,FieldData::LoadEstimationMethod::POWER,0,0,0))->calculate(),
    (new OptimalMotorEfficiency(0,0))->calculate(),
    (new MotorPowerFactor(0,0,Motor::EfficiencyClass::STANDARD,0,FieldData::LoadEstimationMethod::POWER,0,0,0))->calculate(),
    (new OptimalMotorPowerFactor(0,0))->calculate(),
    (new MotorCurrent(0,0,0))->calculate(),
    (new OptimalMotorCurrent(0,0))->calculate(),
    (new MotorPower(0,0,0,0))->calculate(),
    (new OptimalMotorPower(0,0))->calculate(),
    (new AnnualEnergy(0,0))->calculate(),
    (new AnnualEnergy(0,0))->calculate(),
    (new AnnualCost(0,0))->calculate(),
    (new AnnualCost(0,0))->calculate(),
    -1,
    (new AnnualSavingsPotential(0,0))->calculate(),
    -1,
    (new OptimizationRating(0,0))->calculate()
  });
  args.GetReturnValue().Set(r);
}

void init(Local<Object> exports) {
  NODE_SET_METHOD(exports, "results", Results);
}

NODE_MODULE(bridge, init)

<|endoftext|>


<commit_before><commit_msg>Fix Coverity NO_EFFECT defect. Comparing unsigned greater than or equal zero is always true.<commit_after><|endoftext|>


<commit_before><commit_msg>POSIX: Delete ThreadParams on newly created threads ASAP.<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2017 Franka Emika GmbH
// Use of this source code is governed by the Apache-2.0 license, see LICENSE

#include <Eigen/Dense>
#include <Eigen/Geometry>

#include<franka/lowpass_filter.h>

namespace franka {

double lowpassFilter(double sample_time, double y, double y_last, double cutoff_frequency) {
  if (sample_time < 0 || !std::isfinite(sample_time)) {
    throw std::invalid_argument("lowpass-filter: sample_time is negative, infinite or NaN.");
  }
  if (cutoff_frequency <= 0 || !std::isfinite(cutoff_frequency)) {
    throw std::invalid_argument(
        "lowpass-filter: cutoff_frequency is zero, negative, infinite or NaN.");
  }
  if (!std::isfinite(y) || !std::isfinite(y_last)) {
    throw std::invalid_argument(
        "lowpass-filter: current or past input value of the signal to be filtered is infinite or "
        "NaN.");
  }
  double gain = sample_time / (sample_time + (1.0 / (2.0 * M_PI * cutoff_frequency)));
  return gain * y + (1 - gain) * y_last;
}

std::array<double, 16> CartesianLowpassFilter(double sample_time,
                                                     std::array<double, 16> y,
                                                     std::array<double, 16> y_last,
                                                     double cutoff_frequency) {
  if (sample_time < 0 || !std::isfinite(sample_time)) {
    throw std::invalid_argument(
        "Cartesian lowpass-filter: sample_time is negative, infinite or NaN.");
  }
  if (cutoff_frequency <= 0 || !std::isfinite(cutoff_frequency)) {
    throw std::invalid_argument(
        "Cartesian lowpass-filter: cutoff_frequency is zero, negative, infinite or NaN.");
  }
  for (size_t i = 0; i < y.size(); i++) {
    if (!std::isfinite(y[i]) || !std::isfinite(y_last[i])) {
      throw std::invalid_argument(
          "Cartesian lowpass-filter: current or past input value of the signal to be filtered is "
          "infinite or "
          "NaN.");
    }
  }
  Eigen::Affine3d transform(Eigen::Matrix4d::Map(y.data()));
  Eigen::Affine3d transform_last(Eigen::Matrix4d::Map(y_last.data()));
  Eigen::Quaterniond orientation(transform.linear());
  Eigen::Quaterniond orientation_last(transform_last.linear());

  double gain = sample_time / (sample_time + (1.0 / (2.0 * M_PI * cutoff_frequency)));
  transform.translation() =
      gain * transform.translation() + (1.0 - gain) * transform_last.translation();
  orientation_last = orientation_last.slerp(gain, orientation);

  transform.linear() << orientation_last.normalized().toRotationMatrix();
  std::array<double, 16> filtered_values{};
  Eigen::Map<Eigen::Matrix4d>(&filtered_values[0], 4, 4) = transform.matrix();

  return filtered_values;
}
}  // namespace franka<commit_msg>Make format.<commit_after>// Copyright (c) 2017 Franka Emika GmbH
// Use of this source code is governed by the Apache-2.0 license, see LICENSE

#include <Eigen/Dense>
#include <Eigen/Geometry>

#include <franka/lowpass_filter.h>

namespace franka {

double lowpassFilter(double sample_time, double y, double y_last, double cutoff_frequency) {
  if (sample_time < 0 || !std::isfinite(sample_time)) {
    throw std::invalid_argument("lowpass-filter: sample_time is negative, infinite or NaN.");
  }
  if (cutoff_frequency <= 0 || !std::isfinite(cutoff_frequency)) {
    throw std::invalid_argument(
        "lowpass-filter: cutoff_frequency is zero, negative, infinite or NaN.");
  }
  if (!std::isfinite(y) || !std::isfinite(y_last)) {
    throw std::invalid_argument(
        "lowpass-filter: current or past input value of the signal to be filtered is infinite or "
        "NaN.");
  }
  double gain = sample_time / (sample_time + (1.0 / (2.0 * M_PI * cutoff_frequency)));
  return gain * y + (1 - gain) * y_last;
}

std::array<double, 16> CartesianLowpassFilter(double sample_time,
                                              std::array<double, 16> y,
                                              std::array<double, 16> y_last,
                                              double cutoff_frequency) {
  if (sample_time < 0 || !std::isfinite(sample_time)) {
    throw std::invalid_argument(
        "Cartesian lowpass-filter: sample_time is negative, infinite or NaN.");
  }
  if (cutoff_frequency <= 0 || !std::isfinite(cutoff_frequency)) {
    throw std::invalid_argument(
        "Cartesian lowpass-filter: cutoff_frequency is zero, negative, infinite or NaN.");
  }
  for (size_t i = 0; i < y.size(); i++) {
    if (!std::isfinite(y[i]) || !std::isfinite(y_last[i])) {
      throw std::invalid_argument(
          "Cartesian lowpass-filter: current or past input value of the signal to be filtered is "
          "infinite or "
          "NaN.");
    }
  }
  Eigen::Affine3d transform(Eigen::Matrix4d::Map(y.data()));
  Eigen::Affine3d transform_last(Eigen::Matrix4d::Map(y_last.data()));
  Eigen::Quaterniond orientation(transform.linear());
  Eigen::Quaterniond orientation_last(transform_last.linear());

  double gain = sample_time / (sample_time + (1.0 / (2.0 * M_PI * cutoff_frequency)));
  transform.translation() =
      gain * transform.translation() + (1.0 - gain) * transform_last.translation();
  orientation_last = orientation_last.slerp(gain, orientation);

  transform.linear() << orientation_last.normalized().toRotationMatrix();
  std::array<double, 16> filtered_values{};
  Eigen::Map<Eigen::Matrix4d>(&filtered_values[0], 4, 4) = transform.matrix();

  return filtered_values;
}
}  // namespace franka<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <cblas.h>
#include <omp.h>
#include "config.h"

int main(int argc, char * argv[]) {
    long m, n, k;
    if (argc==2) {
        m = atoi(argv[1]);
        n = m;
        k = m;
    }
    else
        if (argc==4) {
            m = atoi(argv[1]);
            n = atoi(argv[2]);
            k = atoi(argv[3]);
        }
        else
            return -1;
    t_float *A, *B, *C;
    double dtime;
    size_t i;
    // TODO: move this to shared module
    fprintf(stderr, "doing clbas\n");
    A = (t_float*) malloc(sizeof(t_float)*m*n);
    B = (t_float*) malloc(sizeof(t_float)*n*k);
    C = (t_float*) malloc(sizeof(t_float)*m*k);
    for(i=0; i<m*n; i++) { A[i] = rand()/RAND_MAX;}
    for(i=0; i<n*k; i++) { B[i] = rand()/RAND_MAX;}
    fprintf(stderr, "done random init\n");

    dtime = omp_get_wtime();
    cblas_sgemm(CblasColMajor, CblasNoTrans, CblasTrans,n,n,n, 1, A, n, B, n, 1, C ,n);
    dtime = omp_get_wtime() - dtime;
    double gflop = (2.0 * m * n * k) / (1024 * 1024 * 1024);
    double gflops = gflop / dtime;
    printf("time: \t%f\n", dtime);
    printf("gflops/s: \t%f\n", gflops);
}
<commit_msg>correct sized in clbas call<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <cblas.h>
#include <omp.h>
#include "config.h"

int main(int argc, char * argv[]) {
    long unsigned m, n, k;
    if (argc==2) {
        m = atoi(argv[1]);
        n = m;
        k = m;
    }
    else
        if (argc==4) {
            m = atoi(argv[1]);
            n = atoi(argv[2]);
            k = atoi(argv[3]);
        }
        else
            return -1;
    t_float *A, *B, *C;
    double dtime;
    size_t i;
    // TODO: move this to shared module
    fprintf(stderr, "doing clbas\n");
    A = (t_float*) malloc(sizeof(t_float)*m*n);
    B = (t_float*) malloc(sizeof(t_float)*n*k);
    C = (t_float*) malloc(sizeof(t_float)*m*k);
    for(i=0; i<m*n; i++) { A[i] = rand()/RAND_MAX;}
    for(i=0; i<n*k; i++) { B[i] = rand()/RAND_MAX;}
    fprintf(stderr, "done random init\n");

    dtime = omp_get_wtime();
    cblas_sgemm(CblasColMajor, CblasNoTrans, CblasTrans, m, n, k, 1, A, m, B, n, 1, C ,m);
    dtime = omp_get_wtime() - dtime;
    double gflop = (2.0 * m * n * k) / (1024 * 1024 * 1024);
    double gflops = gflop / dtime;
    printf("time: \t%f\n", dtime);
    printf("gflops/s: \t%f\n", gflops);
}
<|endoftext|>