├── src ├── Makevars ├── RcppExports.cpp ├── hello.cpp ├── sliding.cpp ├── common.cpp └── movavg.cpp ├── .gitignore ├── .Rbuildignore ├── NAMESPACE ├── inst ├── streamulus-doc │ ├── SimpleExampleGraph.jpg │ └── slides │ │ └── Aarhus_140612.pdf ├── examples │ ├── GNUmakefile │ ├── A_hello_world.cpp │ ├── D_sliding_window_function.cpp │ ├── B_common_subexpression.cpp │ └── C_user_defined_functions_and_filters.cpp ├── tests │ ├── GNUmakefile │ ├── tests.cpp │ ├── operator_functors_test.hpp │ ├── unit_test_api.h │ ├── operator_subscribe_test.hpp │ ├── operator_subscribe_test.cpp │ └── operator_functors_test.cpp ├── include │ ├── RcppStreams.h │ ├── streamulus.h │ ├── subscription.h │ ├── funcs.h │ ├── strop_return_type.h │ ├── stream_base.h │ ├── stream.h │ ├── input_stream.h │ ├── strop_stream_producer.h │ ├── graph.h │ ├── sliding_window_func.h │ ├── strop.h │ ├── strop_sliding_window.h │ ├── strop_data_source.h │ ├── composed_func.h │ ├── sliding_window_library.h │ ├── strop_base.h │ ├── streamify.h │ ├── strop_func.h │ ├── grammar.h │ ├── engine.h │ ├── transforms.h │ └── operators.h └── NEWS.Rd ├── cleanup ├── man ├── helloStream.Rd ├── slidingWindow.Rd ├── commonSubexpressions.Rd └── crossAlert.Rd ├── .github └── workflows │ └── ci.yaml ├── DESCRIPTION ├── README.md ├── R └── RcppExports.R └── ChangeLog /src/Makevars: -------------------------------------------------------------------------------- 1 | 2 | ## We need the header in inst/include 3 | PKG_CPPFLAGS = -I../inst/include/ 4 | 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | src/*.o 6 | src/*.so 7 | src/*.dll 8 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | LICENSE 4 | ^\.travis\.yml 5 | ^.*\.tar\.gz 6 | ^\.github 7 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | useDynLib(RcppStreams, .registration=TRUE) 2 | exportPattern("^[[:alpha:]]+") 3 | 4 | importFrom(Rcpp, evalCpp) 5 | -------------------------------------------------------------------------------- /inst/streamulus-doc/SimpleExampleGraph.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eddelbuettel/rcppstreams/HEAD/inst/streamulus-doc/SimpleExampleGraph.jpg -------------------------------------------------------------------------------- /inst/streamulus-doc/slides/Aarhus_140612.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eddelbuettel/rcppstreams/HEAD/inst/streamulus-doc/slides/Aarhus_140612.pdf -------------------------------------------------------------------------------- /inst/examples/GNUmakefile: -------------------------------------------------------------------------------- 1 | 2 | sources := $(wildcard *.cpp) 3 | programs := $(sources:.cpp=) 4 | 5 | CXXFLAGS = -DUSE_MAIN -Wall -pedantic -march=native 6 | 7 | all: $(programs) 8 | 9 | clean: 10 | rm -f $(programs) 11 | -------------------------------------------------------------------------------- /cleanup: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -f src/*.o src/*.so src/symbols.rds 4 | 5 | rm -rf vignettes/auto/ vignettes/*.log vignettes/*.aux vignettes/*.out vignettes/*.tex \ 6 | vignettes/*.blg vignettes/*.bbl 7 | 8 | find . -name \*~ -exec rm {} \; 9 | 10 | -------------------------------------------------------------------------------- /inst/tests/GNUmakefile: -------------------------------------------------------------------------------- 1 | 2 | sources := $(wildcard *.cpp) 3 | #programs := $(sources:.cpp=) 4 | programs := tests 5 | 6 | CXXFLAGS = -I../src -Wall -pedantic -march=native 7 | 8 | all: $(programs) 9 | 10 | $(programs): $(sources) 11 | 12 | clean: 13 | rm -f $(programs) 14 | -------------------------------------------------------------------------------- /inst/tests/tests.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include "operator_functors_test.hpp" 5 | #include "operator_subscribe_test.hpp" 6 | 7 | int main(int argc , char *argv[]) { 8 | 9 | streamulus::operator_functors_unit_tests functorsTests; 10 | functorsTests.Run(); 11 | 12 | streamulus::operator_subscribe_unit_tests subscribeTests; 13 | subscribeTests.Run(); 14 | 15 | return 0; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /man/helloStream.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/RcppExports.R 3 | \name{helloStream} 4 | \alias{helloStream} 5 | \title{Print some hello messages} 6 | \usage{ 7 | helloStream() 8 | } 9 | \value{ 10 | An unconditional TRUE value 11 | } 12 | \description{ 13 | This is an example function illustrating Streamulus 14 | } 15 | \examples{ 16 | \dontrun{ 17 | helloStream() 18 | } 19 | } 20 | \author{ 21 | Dirk Eddelbuettel 22 | } 23 | -------------------------------------------------------------------------------- /man/slidingWindow.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/RcppExports.R 3 | \name{slidingWindow} 4 | \alias{slidingWindow} 5 | \title{Sliding window function example} 6 | \usage{ 7 | slidingWindow() 8 | } 9 | \value{ 10 | An unconditional TRUE value 11 | } 12 | \description{ 13 | This is an example function illustrating Streamulus 14 | } 15 | \examples{ 16 | \dontrun{ 17 | slidingWindow() 18 | } 19 | } 20 | \author{ 21 | Dirk Eddelbuettel 22 | } 23 | -------------------------------------------------------------------------------- /man/commonSubexpressions.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/RcppExports.R 3 | \name{commonSubexpressions} 4 | \alias{commonSubexpressions} 5 | \title{Common 'greeting' carried across several expressions} 6 | \usage{ 7 | commonSubexpressions() 8 | } 9 | \value{ 10 | An unconditional TRUE value 11 | } 12 | \description{ 13 | This is an example function illustrating Streamulus 14 | } 15 | \examples{ 16 | \dontrun{ 17 | commonSubexpressions() 18 | } 19 | } 20 | \author{ 21 | Dirk Eddelbuettel 22 | } 23 | -------------------------------------------------------------------------------- /man/crossAlert.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/RcppExports.R 3 | \name{crossAlert} 4 | \alias{crossAlert} 5 | \title{Alert for cross of two moving averages} 6 | \usage{ 7 | crossAlert(f1, f2) 8 | } 9 | \arguments{ 10 | \item{f1}{Parameter for the slower exponential moving average} 11 | 12 | \item{f2}{Parameter for the faster exponential moving average} 13 | } 14 | \value{ 15 | An unconditional TRUE value 16 | } 17 | \description{ 18 | This is an example function illustrating Streamulus 19 | } 20 | \examples{ 21 | \dontrun{ 22 | crossAlert(10,20) 23 | } 24 | } 25 | \author{ 26 | Dirk Eddelbuettel 27 | } 28 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | # Run CI for R using https://eddelbuettel.github.io/r-ci/ 2 | 3 | name: ci 4 | 5 | on: 6 | push: 7 | pull_request: 8 | 9 | env: 10 | _R_CHECK_FORCE_SUGGESTS_: "false" 11 | 12 | jobs: 13 | ci: 14 | strategy: 15 | matrix: 16 | include: 17 | #- {os: macOS-latest} 18 | - {os: ubuntu-latest} 19 | 20 | runs-on: ${{ matrix.os }} 21 | 22 | steps: 23 | - name: Checkout 24 | uses: actions/checkout@v4 25 | 26 | - name: Setup 27 | uses: eddelbuettel/github-actions/r-ci@master 28 | 29 | - name: Dependencies 30 | run: ./run.sh install_deps 31 | 32 | - name: Test 33 | run: ./run.sh run_tests 34 | 35 | #- name: Coverage 36 | # if: ${{ matrix.os == 'ubuntu-latest' }} 37 | # run: ./run.sh coverage 38 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: RcppStreams 2 | Type: Package 3 | Title: 'Rcpp' Integration of the 'Streamulus' 'DSEL' for Stream Processing 4 | Version: 0.1.4 5 | Date: 2025-01-29 6 | Authors@R: c(person("Dirk", "Eddelbuettel", role = c("aut", "cre"), email = "edd@debian.org", 7 | comment = c(ORCID = "0000-0001-6419-907X")), 8 | person("Irit", "Katriel", role = "aut", comment = "Author of 'Streamulus'")) 9 | Description: The 'Streamulus' (template, header-only) library by 10 | Irit Katriel (at ) 11 | provides a very powerful yet convenient framework for stream 12 | processing. This package connects 'Streamulus' to R by providing 13 | both the header files and all examples. 14 | URL: http://dirk.eddelbuettel.com/code/rcpp.streams.html 15 | BugReports: https://github.com/eddelbuettel/rcppstreams/issues 16 | License: GPL (>= 3) 17 | Depends: R (>= 3.0.0) 18 | Imports: Rcpp 19 | LinkingTo: Rcpp, BH 20 | RoxygenNote: 6.0.1 21 | -------------------------------------------------------------------------------- /inst/include/RcppStreams.h: -------------------------------------------------------------------------------- 1 | // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- 2 | // 3 | // RcppStreams -- Rcpp bindings to Streamulus for Event-based stream processing 4 | // 5 | // Copyright (C) 2015 Dirk Eddelbuettel 6 | // 7 | // This file is part of RcppStreams 8 | // 9 | // RcppStreams is free software: you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation, either version 3 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // RcppStreams is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with RcppStreams. If not, see . 21 | 22 | #include 23 | 24 | // We define a StreamulusOutput object 25 | #define StreamulusOut Rcpp::Rcout 26 | 27 | -------------------------------------------------------------------------------- /inst/tests/operator_functors_test.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // operator_functor_tests.hpp 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #include 23 | 24 | #include "unit_test_api.h" 25 | 26 | namespace streamulus 27 | { 28 | 29 | struct operator_functors_unit_tests : unit_test_api 30 | { 31 | void Run(); 32 | }; 33 | 34 | } // ns streamulus -------------------------------------------------------------------------------- /inst/include/streamulus.h: -------------------------------------------------------------------------------- 1 | // 2 | // streamulus.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | #if !defined(StreamulusOut) 27 | #define StreamulusOut std::cout 28 | #endif 29 | 30 | #include "engine.h" 31 | #include "input_stream.h" 32 | #include "operators.h" 33 | #include "streamify.h" 34 | #include "strop_data_source.h" 35 | 36 | 37 | namespace streamulus 38 | { 39 | typedef Engine Streamulus; 40 | } // ns streamulus 41 | -------------------------------------------------------------------------------- /inst/include/subscription.h: -------------------------------------------------------------------------------- 1 | // 2 | // subscription.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | #include "strop_stream_producer.h" 25 | 26 | namespace streamulus { 27 | 28 | template 29 | struct Subscription 30 | { 31 | typedef const boost::shared_ptr > strop_type; 32 | typedef typename boost::proto::terminal::type terminal_type; 33 | typedef const terminal_type type; 34 | }; 35 | 36 | } // ns streamulus 37 | -------------------------------------------------------------------------------- /inst/tests/unit_test_api.h: -------------------------------------------------------------------------------- 1 | // 2 | // unit_test_api.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | namespace streamulus 27 | { 28 | struct unit_test_api 29 | { 30 | struct unit_test_failed : public std::exception 31 | {}; 32 | 33 | virtual void Check(bool condition) throw(unit_test_failed) 34 | { 35 | if (!condition) 36 | { 37 | throw unit_test_failed(); 38 | } 39 | } 40 | 41 | virtual void Run()=0; 42 | 43 | }; 44 | 45 | } // ns streamulus -------------------------------------------------------------------------------- /inst/include/funcs.h: -------------------------------------------------------------------------------- 1 | // 2 | // funcs.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | namespace streamulus 25 | { 26 | template 27 | struct ConstFunc 28 | { 29 | public: 30 | ConstFunc(const T& value_) 31 | : mValue(value_) 32 | { 33 | } 34 | 35 | template 36 | struct result 37 | { 38 | typedef typename boost::remove_const::type>::type type; 39 | }; 40 | 41 | typename result::type 42 | operator()() const 43 | { 44 | return mValue; 45 | } 46 | 47 | private: 48 | T mValue; 49 | }; 50 | 51 | } // ns streamulus 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## RcppStreams: Connecting Streamulus and R 2 | 3 | [![CI](https://github.com/eddelbuettel/rcppstreams/workflows/ci/badge.svg)](https://github.com/eddelbuettel/rcppstreams/actions?query=workflow%3Aci) 4 | [![License](https://img.shields.io/badge/license-GPL%20%28%3E=%203%29-brightgreen.svg?style=flat)](https://www.gnu.org/licenses/gpl-3.0.html) 5 | [![CRAN](https://www.r-pkg.org/badges/version/RcppStreams)](https://cran.r-project.org/package=RcppStreams) 6 | [![Dependencies](https://tinyverse.netlify.app/badge/RcppStreams)](https://cran.r-project.org/package=RcppStreams) 7 | [![Downloads](https://cranlogs.r-pkg.org/badges/RcppStreams?color=brightgreen)](https://www.r-pkg.org/pkg/RcppStreams) 8 | [![Last Commit](https://img.shields.io/github/last-commit/eddelbuettel/rcppstreams)](https://github.com/eddelbuettel/rcppstreams) 9 | 10 | ### Background 11 | 12 | The [Streamulus template / header-only library](http://iritkatriel.github.io/streamulus/) 13 | by Irit Katriel provides a very nice C++ stream processing environment--a 14 | domain-specific embedded language for stream processing. 15 | 16 | This package provides the Streamulus headers and uses 17 | [Rcpp](http://dirk.eddelbuettel.com/code/rcpp.html) for a convenient 18 | bi-directional connection to the C++ layer. 19 | 20 | ### See Also 21 | 22 | The [Streamulus](http://iritkatriel.github.io/streamulus/) and 23 | [RcppStreams](http://dirk.eddelbuettel.com/code/rcpp.streams.html) pages. 24 | 25 | ### Authors 26 | 27 | Dirk Eddelbuettel for this package 28 | Irit Katriel for [Streamulus](http://iritkatriel.github.io/streamulus/) 29 | 30 | ### License 31 | 32 | GPL (>= 3) just like [Streamulus](http://iritkatriel.github.io/streamulus/) 33 | 34 | -------------------------------------------------------------------------------- /R/RcppExports.R: -------------------------------------------------------------------------------- 1 | # Generated by using Rcpp::compileAttributes() -> do not edit by hand 2 | # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | #' This is an example function illustrating Streamulus 5 | #' 6 | #' @title Common 'greeting' carried across several expressions 7 | #' @return An unconditional TRUE value 8 | #' @author Dirk Eddelbuettel 9 | #' @examples 10 | #' \dontrun{ 11 | #' commonSubexpressions() 12 | #' } 13 | commonSubexpressions <- function() { 14 | .Call(`_RcppStreams_commonSubexpressions`) 15 | } 16 | 17 | #' This is an example function illustrating Streamulus 18 | #' 19 | #' @title Print some hello messages 20 | #' @return An unconditional TRUE value 21 | #' @author Dirk Eddelbuettel 22 | #' @examples 23 | #' \dontrun{ 24 | #' helloStream() 25 | #' } 26 | helloStream <- function() { 27 | .Call(`_RcppStreams_helloStream`) 28 | } 29 | 30 | #' This is an example function illustrating Streamulus 31 | #' 32 | #' @title Alert for cross of two moving averages 33 | #' @param f1 Parameter for the slower exponential moving average 34 | #' @param f2 Parameter for the faster exponential moving average 35 | #' @return An unconditional TRUE value 36 | #' @author Dirk Eddelbuettel 37 | #' @examples 38 | #' \dontrun{ 39 | #' crossAlert(10,20) 40 | #' } 41 | crossAlert <- function(f1, f2) { 42 | .Call(`_RcppStreams_crossAlert`, f1, f2) 43 | } 44 | 45 | #' This is an example function illustrating Streamulus 46 | #' 47 | #' @title Sliding window function example 48 | #' @return An unconditional TRUE value 49 | #' @author Dirk Eddelbuettel 50 | #' @examples 51 | #' \dontrun{ 52 | #' slidingWindow() 53 | #' } 54 | slidingWindow <- function() { 55 | .Call(`_RcppStreams_slidingWindow`) 56 | } 57 | 58 | -------------------------------------------------------------------------------- /inst/NEWS.Rd: -------------------------------------------------------------------------------- 1 | \name{NEWS} 2 | \title{News for Package \pkg{RcppStreams}} 3 | \newcommand{\cpkg}{\href{http://CRAN.R-project.org/package=#1}{\pkg{#1}}} 4 | 5 | \section{Changes in version 0.1.4 (2024-01-29)}{ 6 | \itemize{ 7 | \item Package maintenance with updates to DESCRIPTION and README.md 8 | \item Continunous integration has been update multiple times 9 | \item No longer set a C++ compilation standard 10 | } 11 | } 12 | 13 | \section{Changes in version 0.1.3 (2019-02-24)}{ 14 | \itemize{ 15 | \item No longer run examples as they upset the UBSAN checks at CRAN 16 | } 17 | } 18 | 19 | \section{Changes in version 0.1.2 (2019-01-05)}{ 20 | \itemize{ 21 | \item Added symbol registration 22 | \item Converted a few files from CRLF to CR [CRAN checks] 23 | \item Added a few final newlines [CRAN checks] 24 | \item Disabled one optional output to enable BH 1.69 builds 25 | } 26 | } 27 | 28 | \section{Changes in version 0.1.1 (2016-08-05)}{ 29 | \itemize{ 30 | \item Compilation is now done using C++11 standards per request of 31 | CRAN to help with an array of newer (pre-release) and older 32 | compilers 33 | \item The Travis CI script was updated to use \code{run.sh} from our 34 | fork; it now also installs all dependencies as binary .deb files. 35 | \item The README.md was updated with additional badges. 36 | \item The DESCRIPTION file now has URL and BugReports entries. 37 | } 38 | } 39 | 40 | \section{Changes in version 0.1.0 (2015-01-30)}{ 41 | \itemize{ 42 | \item First CRAN release 43 | \item Contains all upstream examples and documentation from Streamulus 44 | \item Added Rcpp Attributes wrapping and minimal manual pages 45 | \item Added Travis CI unit testing 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /inst/include/strop_return_type.h: -------------------------------------------------------------------------------- 1 | // 2 | // strop_return_type.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | namespace streamulus 27 | { 28 | template 29 | struct StropReturnType; 30 | 31 | template 32 | struct StropReturnType > 33 | { 34 | typedef typename StropType::result_type type; 35 | }; 36 | 37 | template 38 | struct StropReturnType > 39 | { 40 | typedef typename StropType::result_type type; 41 | }; 42 | 43 | template 44 | struct StropReturnType& > 45 | { 46 | typedef typename StropType::result_type type; 47 | }; 48 | 49 | template 50 | struct StropReturnType& > 51 | { 52 | typedef typename StropType::result_type type; 53 | }; 54 | } // ns streamulus 55 | -------------------------------------------------------------------------------- /inst/include/stream_base.h: -------------------------------------------------------------------------------- 1 | // 2 | // stream_base.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | #include "graph.h" 25 | 26 | namespace streamulus 27 | { 28 | class StreamBase 29 | { 30 | public: 31 | StreamBase() 32 | : mGraph(NULL) 33 | , mIsFeedbackEdge(false) 34 | { 35 | } 36 | 37 | const Graph::edge_descriptor& Descriptor() const 38 | { 39 | return mEdgeDescriptor; 40 | } 41 | 42 | void SetGraph(const Graph::edge_descriptor& desc, Graph* g) 43 | { 44 | mGraph = g; 45 | mEdgeDescriptor = desc; 46 | } 47 | 48 | bool IsFeedbackEdge() 49 | { 50 | return mIsFeedbackEdge; 51 | } 52 | 53 | void SetIsFeedbackEdge(bool v) 54 | { 55 | mIsFeedbackEdge = v; 56 | } 57 | 58 | private: 59 | Graph* mGraph; // no ownership. do not delete. 60 | Graph::edge_descriptor mEdgeDescriptor; 61 | bool mIsFeedbackEdge; 62 | }; 63 | 64 | } // ns streamulus 65 | -------------------------------------------------------------------------------- /inst/include/stream.h: -------------------------------------------------------------------------------- 1 | // 2 | // stream.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | #include "stream_base.h" 25 | #include 26 | #include 27 | 28 | namespace streamulus 29 | { 30 | template 31 | class Stream : public StreamBase 32 | { 33 | public: 34 | 35 | void Append(const T& item) 36 | { 37 | mBuffer.push_back(item); 38 | } 39 | 40 | bool HasMore() 41 | { 42 | return !mBuffer.empty(); 43 | } 44 | 45 | bool IsValid() 46 | { 47 | return mLastValue || !mBuffer.empty(); 48 | } 49 | 50 | const T& Current() 51 | { 52 | if (!mBuffer.empty()) 53 | { 54 | mLastValue = mBuffer.front(); 55 | mBuffer.pop_front(); 56 | } 57 | 58 | assert(mLastValue); 59 | 60 | // No new data - return last 61 | return *mLastValue; 62 | } 63 | 64 | private: 65 | 66 | std::deque mBuffer; 67 | boost::optional mLastValue; 68 | }; 69 | 70 | } // ns streamulus 71 | -------------------------------------------------------------------------------- /inst/include/input_stream.h: -------------------------------------------------------------------------------- 1 | // 2 | // input_stream.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | #include "strop_data_source.h" 25 | 26 | #include 27 | 28 | namespace streamulus 29 | { 30 | // Convenience utilities for defining input streams 31 | 32 | template 33 | struct InputStream 34 | { 35 | typedef boost::shared_ptr > data_source_t; 36 | typedef typename boost::proto::terminal::type proto_expression; 37 | typedef const proto_expression type; 38 | }; 39 | 40 | // Create a new stream 41 | template 42 | typename InputStream::type NewInputStream(const char* name, bool verbose) 43 | { 44 | typename InputStream::proto_expression expr = {boost::make_shared >(name, verbose)}; 45 | return expr; 46 | } 47 | 48 | // Add an input to the stream 49 | template 50 | void InputStreamPut(typename InputStream::type terminal, const T& value) 51 | { 52 | boost::proto::value(terminal)->Tick(value); 53 | } 54 | 55 | 56 | } // ns streamulus 57 | -------------------------------------------------------------------------------- /inst/include/strop_stream_producer.h: -------------------------------------------------------------------------------- 1 | // 2 | // strop_stream_generator.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | #include "engine.h" 25 | #include "stream.h" 26 | #include "strop_base.h" 27 | 28 | #include 29 | 30 | namespace streamulus 31 | { 32 | 33 | template 34 | class StropStreamProducer 35 | : public StropBase 36 | { 37 | public: 38 | 39 | typedef R result_type; 40 | 41 | virtual ~StropStreamProducer() 42 | { 43 | } 44 | 45 | void Output(const R& value) 46 | { 47 | if (!GetEngine()) 48 | return; 49 | 50 | GetEngine()->template Output(mVertexDescriptor,value); 51 | mCurrentValue = value; 52 | } 53 | 54 | typedef boost::shared_ptr< Stream > OutputStreamPtr; 55 | 56 | OutputStreamPtr MakeOutputStream() 57 | { 58 | OutputStreamPtr stream = boost::make_shared< Stream >(); 59 | if (mCurrentValue) 60 | stream->Append(*mCurrentValue); 61 | return stream; 62 | } 63 | 64 | private: 65 | boost::optional mCurrentValue; 66 | }; 67 | 68 | 69 | } // ns streamulus 70 | -------------------------------------------------------------------------------- /inst/include/graph.h: -------------------------------------------------------------------------------- 1 | // 2 | // graph.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | namespace streamulus 27 | { 28 | 29 | struct StropTag { typedef boost::vertex_property_tag kind; }; 30 | struct StreamTag { typedef boost::edge_property_tag kind; }; 31 | 32 | class StropBase; 33 | class StreamBase; 34 | 35 | typedef boost::shared_ptr StropPtr; 36 | typedef boost::shared_ptr StreamPtr; 37 | 38 | 39 | typedef boost::adjacency_list 43 | , boost::property 44 | > BoostGraph; 45 | 46 | class Graph : public BoostGraph 47 | { 48 | public: 49 | typedef BoostGraph type; 50 | 51 | StropPtr& operator[](const BoostGraph::vertex_descriptor& d) 52 | { 53 | return boost::get(StropTag(), *this)[d]; 54 | } 55 | 56 | StreamPtr& operator[](const BoostGraph::edge_descriptor& d) 57 | { 58 | return boost::get(StreamTag(), *this)[d]; 59 | } 60 | }; 61 | 62 | 63 | } // ns streamulus 64 | -------------------------------------------------------------------------------- /inst/include/sliding_window_func.h: -------------------------------------------------------------------------------- 1 | // 2 | // sliding_window_func.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #include 23 | 24 | #include "strop_sliding_window.h" 25 | 26 | namespace streamulus 27 | { 28 | template 29 | class WindowFunc 30 | { 31 | public: 32 | 33 | WindowFunc() 34 | : mFunction(F()) 35 | { 36 | } 37 | 38 | WindowFunc(const F& f) 39 | : mFunction(f) 40 | { 41 | } 42 | 43 | template struct result; 44 | 45 | template 46 | struct result 47 | { 48 | typedef typename F::template value_type::type)>::type type; 49 | }; 50 | 51 | template 52 | boost::optional::type> 53 | operator()(const WA& window_update) 54 | { 55 | if (window_update.first == DATA_OUT) 56 | { 57 | mFunction.Remove(window_update.second); 58 | return boost::none; 59 | } 60 | mFunction.Insert(window_update.second); 61 | return mFunction.Value(); 62 | } 63 | 64 | private: 65 | F mFunction; 66 | }; 67 | 68 | } // ns streamulus 69 | -------------------------------------------------------------------------------- /src/RcppExports.cpp: -------------------------------------------------------------------------------- 1 | // Generated by using Rcpp::compileAttributes() -> do not edit by hand 2 | // Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | #include "../inst/include/RcppStreams.h" 5 | #include 6 | 7 | using namespace Rcpp; 8 | 9 | // commonSubexpressions 10 | bool commonSubexpressions(); 11 | RcppExport SEXP _RcppStreams_commonSubexpressions() { 12 | BEGIN_RCPP 13 | Rcpp::RObject rcpp_result_gen; 14 | Rcpp::RNGScope rcpp_rngScope_gen; 15 | rcpp_result_gen = Rcpp::wrap(commonSubexpressions()); 16 | return rcpp_result_gen; 17 | END_RCPP 18 | } 19 | // helloStream 20 | bool helloStream(); 21 | RcppExport SEXP _RcppStreams_helloStream() { 22 | BEGIN_RCPP 23 | Rcpp::RObject rcpp_result_gen; 24 | Rcpp::RNGScope rcpp_rngScope_gen; 25 | rcpp_result_gen = Rcpp::wrap(helloStream()); 26 | return rcpp_result_gen; 27 | END_RCPP 28 | } 29 | // crossAlert 30 | bool crossAlert(int f1, int f2); 31 | RcppExport SEXP _RcppStreams_crossAlert(SEXP f1SEXP, SEXP f2SEXP) { 32 | BEGIN_RCPP 33 | Rcpp::RObject rcpp_result_gen; 34 | Rcpp::RNGScope rcpp_rngScope_gen; 35 | Rcpp::traits::input_parameter< int >::type f1(f1SEXP); 36 | Rcpp::traits::input_parameter< int >::type f2(f2SEXP); 37 | rcpp_result_gen = Rcpp::wrap(crossAlert(f1, f2)); 38 | return rcpp_result_gen; 39 | END_RCPP 40 | } 41 | // slidingWindow 42 | bool slidingWindow(); 43 | RcppExport SEXP _RcppStreams_slidingWindow() { 44 | BEGIN_RCPP 45 | Rcpp::RObject rcpp_result_gen; 46 | Rcpp::RNGScope rcpp_rngScope_gen; 47 | rcpp_result_gen = Rcpp::wrap(slidingWindow()); 48 | return rcpp_result_gen; 49 | END_RCPP 50 | } 51 | 52 | static const R_CallMethodDef CallEntries[] = { 53 | {"_RcppStreams_commonSubexpressions", (DL_FUNC) &_RcppStreams_commonSubexpressions, 0}, 54 | {"_RcppStreams_helloStream", (DL_FUNC) &_RcppStreams_helloStream, 0}, 55 | {"_RcppStreams_crossAlert", (DL_FUNC) &_RcppStreams_crossAlert, 2}, 56 | {"_RcppStreams_slidingWindow", (DL_FUNC) &_RcppStreams_slidingWindow, 0}, 57 | {NULL, NULL, 0} 58 | }; 59 | 60 | RcppExport void R_init_RcppStreams(DllInfo *dll) { 61 | R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); 62 | R_useDynamicSymbols(dll, FALSE); 63 | } 64 | -------------------------------------------------------------------------------- /inst/include/strop.h: -------------------------------------------------------------------------------- 1 | // 2 | // strop.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | 30 | #include "strop_stream_producer.h" 31 | 32 | namespace streamulus 33 | { 34 | 35 | template // F = function signature 36 | class Strop 37 | : public StropStreamProducer::type> 38 | { 39 | public: 40 | 41 | virtual ~Strop() 42 | { 43 | } 44 | 45 | template // a fusion sequence of the inputs 46 | void SetInputs(const Inputs& inputs) 47 | { 48 | mInputs=inputs; 49 | } 50 | 51 | template 52 | Stream* const Input() 53 | { 54 | return boost::fusion::at_c(mInputs).get(); 55 | } 56 | 57 | 58 | private: 59 | template 60 | struct MakeStreamPtrType 61 | { 62 | typedef boost::shared_ptr > type; 63 | }; 64 | typedef boost::function_types::parameter_types param_types; 65 | typedef typename boost::mpl::transform >::type input_types; 66 | typename boost::fusion::result_of::as_vector::type mInputs; 67 | }; 68 | 69 | 70 | } // ns streamulus 71 | -------------------------------------------------------------------------------- /inst/include/strop_sliding_window.h: -------------------------------------------------------------------------------- 1 | // 2 | // strop_sliding_window.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | namespace streamulus 27 | { 28 | 29 | enum WindowInOut { DATA_IN, DATA_OUT }; 30 | 31 | template 32 | struct WindowUpdateType 33 | { 34 | typedef std::pair type; 35 | }; 36 | 37 | template 38 | struct WindowBaseType; 39 | 40 | template 41 | struct WindowBaseType > 42 | { 43 | typedef T type; 44 | }; 45 | 46 | template 47 | class Window : public Strop::type(T)> 48 | { 49 | public: 50 | typedef typename WindowUpdateType::type R; 51 | 52 | Window(size_t size) 53 | : mBuffer(size) 54 | { 55 | } 56 | 57 | virtual void Work() 58 | { 59 | Stream* const input(Strop::template Input()); 60 | 61 | assert(input->IsValid()); 62 | 63 | while (input->HasMore()) 64 | { 65 | if (mBuffer.reserve() == 0) 66 | StropStreamProducer::Output(std::make_pair(DATA_OUT,mBuffer.front())); 67 | 68 | const T& value(input->Current()); 69 | mBuffer.push_back(value); 70 | StropStreamProducer::Output(std::make_pair(DATA_IN,value)); 71 | } 72 | } 73 | 74 | private: 75 | boost::circular_buffer mBuffer; 76 | }; 77 | 78 | } // ns streamulus 79 | -------------------------------------------------------------------------------- /inst/include/strop_data_source.h: -------------------------------------------------------------------------------- 1 | // 2 | // strop_data_source.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | #include "strop_stream_producer.h" 27 | 28 | namespace streamulus 29 | { 30 | 31 | template 32 | class DataSource : public StropStreamProducer 33 | { 34 | public: 35 | 36 | typedef R result_type; 37 | 38 | DataSource(const char* name, bool verbose) 39 | : mIsValid(false) 40 | , mIsVerbose(verbose) 41 | { 42 | StropStreamProducer::SetDisplayName(name); 43 | } 44 | 45 | virtual void Work() 46 | { 47 | // Return the last tick's value. 48 | if (mIsValid) 49 | StropStreamProducer::Output(mLastValue); 50 | } 51 | 52 | inline bool IsVerbose() 53 | { 54 | return mIsVerbose; 55 | } 56 | 57 | void Tick(const R& value) 58 | { 59 | if (IsVerbose()) 60 | StreamulusOut << "------------- " 61 | << StropStreamProducer::DisplayName() << " <-- " 62 | << value << " -------------" << std::endl; 63 | StropStreamProducer::Output(value); 64 | mLastValue = value; 65 | mIsValid = true; 66 | } 67 | 68 | private: 69 | R mLastValue; 70 | bool mIsValid; 71 | bool mIsVerbose; 72 | }; 73 | 74 | } // ns streamulus 75 | -------------------------------------------------------------------------------- /inst/include/composed_func.h: -------------------------------------------------------------------------------- 1 | // 2 | // compose_fn.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | 23 | // Take two functions F(x) and G(x), and create the function H(x)=F(G(x)) 24 | // Based on 25 | // (http://cpp-next.com/archive/2010/11/expressive-c-fun-with-function-composition/). 26 | 27 | 28 | #pragma once 29 | 30 | #include 31 | 32 | namespace streamulus 33 | { 34 | 35 | struct ArgType; 36 | 37 | template 38 | class ComposedFunc; 39 | 40 | template 41 | class ComposedFunc 42 | { 43 | public: 44 | 45 | 46 | explicit ComposedFunc(const F& f_ = F(), const G& g_ = G()) 47 | : f(f_) 48 | , g(g_) 49 | { 50 | StreamulusOut << "Composed two functions!" << std::endl; 51 | } 52 | 53 | template 54 | struct result; 55 | 56 | template 57 | struct result 58 | { 59 | typedef typename boost::result_of::type G_result_type; 60 | typedef typename boost::result_of::type F_result_type; 61 | typedef F_result_type type; 62 | }; 63 | 64 | template 65 | typename boost::optional(Arg)>::type> 66 | operator()(const Arg& arg) 67 | { 68 | boost::optional(Arg)>::G_result_type> g_res = g(arg); 69 | if (!g_res) 70 | return boost::none; 71 | boost::optional(Arg)>::F_result_type> f_res = f(*g_res); 72 | if (!f_res) 73 | return boost::none; 74 | return *f_res; 75 | } 76 | 77 | private: 78 | F f; 79 | G g; 80 | }; 81 | 82 | 83 | } // ns streamulus 84 | 85 | -------------------------------------------------------------------------------- /inst/tests/operator_subscribe_test.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // operator_subscribe_tests.hpp 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #include "operators.h" 23 | #include "unit_test_api.h" 24 | 25 | // 26 | // operator subscribe test 27 | // 28 | // Subscribe an expression for each operator and check that it computes 29 | // something reasonable. 30 | // 31 | 32 | #include "../src/streamulus.h" 33 | 34 | namespace streamulus 35 | { 36 | namespace bp = boost::proto; 37 | 38 | struct assert_eq 39 | { 40 | static int tests_passed; 41 | 42 | template struct result; 43 | 44 | template 45 | struct result 46 | { 47 | typedef bool type; 48 | }; 49 | 50 | template 51 | typename result::type 52 | operator()(const T1& v1, const T2& v2) const 53 | { 54 | bool result = (v1 == v2); 55 | if (! result) 56 | std::cout << "********* Test Failed! " << v1 << "!=" << v2 << " *********" << std::endl; 57 | 58 | if(result) 59 | tests_passed++; 60 | return result; 61 | } 62 | }; 63 | 64 | struct operator_subscribe_unit_tests : unit_test_api 65 | { 66 | public: 67 | 68 | operator_subscribe_unit_tests() 69 | { 70 | tests_run = 0; 71 | } 72 | 73 | void Run(); 74 | 75 | private: 76 | template 77 | void RunTest(Expr& expr, ExpectedValueType expected) 78 | { 79 | tests_run++; 80 | Streamulus engine; 81 | engine.Subscribe(Streamify(expr, expected)); 82 | } 83 | 84 | void OpsBetweenTerminals(); 85 | 86 | void OpsBetweenTerminalAndConst(); 87 | 88 | int tests_run; 89 | }; 90 | 91 | } // ns streamulus -------------------------------------------------------------------------------- /inst/examples/A_hello_world.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // hello_world.cpp 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | 23 | // *************** Example A: Hello Stream! *************** 24 | // Below is a complete Streamulus program that receives 25 | // as input a stream of strings and greets each one 26 | // of them. 27 | // 28 | // The output of the program is below. The Streamulus InputStream 29 | // prints the values that arrive on the stream, and our program 30 | // prints the rest: 31 | // 32 | // ------------- Input Stream <-- World ------------- 33 | // Hello World! 34 | // ------------- Input Stream <-- London ------------- 35 | // Hello London! 36 | // ------------- Input Stream <-- Streamulus ------------- 37 | // Hello Streamulus! 38 | // 39 | // ******************************************************** 40 | 41 | #include "../src/streamulus.h" 42 | 43 | #include 44 | 45 | // print is a functor that prints whatever it gets. 46 | // Stremify is a stream function that prints every 47 | // element of a stream. 48 | struct print 49 | { 50 | template struct result; 51 | 52 | // Boost result-of protocol (not necessary in C++11) 53 | template 54 | struct result 55 | { 56 | typedef T type; 57 | }; 58 | 59 | // The actual function 60 | template 61 | typename result::type 62 | operator()(const T& value) const 63 | { 64 | std::cout << value << std::endl; 65 | return value; 66 | } 67 | }; 68 | 69 | void hello_stream(); 70 | 71 | void hello_stream() 72 | { 73 | using namespace streamulus; 74 | 75 | // Define an input stream of strings, whose name is "Input Stream" 76 | InputStream::type s = NewInputStream("Input Stream", true /* verbose */); 77 | 78 | // Construct a streamulus instance 79 | Streamulus streamulus_engine; 80 | 81 | // Define some constants 82 | std::string hello("Hello "); 83 | std::string exc("!"); 84 | 85 | // For each element of the stream: 86 | // compute a greeting 87 | // print it 88 | // emit it into the output stream 89 | // 90 | 91 | 92 | streamulus_engine.Subscribe(Streamify(hello + s + exc)); 93 | 94 | // Insert data to the input stream 95 | InputStreamPut(s, "World"); 96 | InputStreamPut(s, "London"); 97 | InputStreamPut(s, "Streamulus"); 98 | } 99 | 100 | #if defined(USE_MAIN) 101 | int main() 102 | { 103 | hello_stream(); 104 | return 0; 105 | } 106 | #endif 107 | -------------------------------------------------------------------------------- /inst/include/sliding_window_library.h: -------------------------------------------------------------------------------- 1 | // 2 | // sliding_window_library.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | #include "boost/tuple/tuple.hpp" 25 | #include "boost/tuple/tuple_io.hpp" 26 | 27 | namespace streamulus 28 | { 29 | struct WindowCount 30 | { 31 | public: 32 | WindowCount() : mCount(0) 33 | { 34 | } 35 | 36 | template 37 | struct value_type 38 | { 39 | typedef long type; 40 | }; 41 | 42 | template 43 | void Insert(const T& value) 44 | { 45 | mCount++; 46 | } 47 | 48 | template 49 | void Remove(const T& value) 50 | { 51 | mCount--; 52 | } 53 | 54 | long Value() const 55 | { 56 | return mCount; 57 | } 58 | 59 | private: 60 | long mCount; 61 | }; 62 | 63 | 64 | template 65 | struct WindowSum 66 | { 67 | public: 68 | WindowSum() : mSum(0) 69 | { 70 | } 71 | 72 | template 73 | struct value_type 74 | { 75 | typedef T type; 76 | }; 77 | 78 | void Insert(const T& value) 79 | { 80 | mSum += value; 81 | } 82 | 83 | void Remove(const T& value) 84 | { 85 | mSum -= value; 86 | } 87 | 88 | const T& Value() const 89 | { 90 | return mSum; 91 | } 92 | 93 | private: 94 | T mSum; 95 | }; 96 | 97 | template 98 | struct WindowAvg 99 | { 100 | public: 101 | WindowAvg() 102 | { 103 | } 104 | 105 | typedef boost::tuple OutputType; 106 | 107 | template 108 | struct value_type 109 | { 110 | typedef OutputType type; 111 | }; 112 | 113 | void Insert(const T& value) 114 | { 115 | mSum.Insert(value); 116 | mCount.Insert(value); 117 | } 118 | 119 | void Remove(const T& value) 120 | { 121 | mSum.Remove(value); 122 | mCount.Remove(value); 123 | } 124 | 125 | const OutputType Value() const 126 | { 127 | long count(mCount.Value()); 128 | double sum(sum); 129 | double avg(count ? sum/count : 0); 130 | return boost::make_tuple(avg,sum,count); 131 | } 132 | 133 | private: 134 | WindowSum mSum; 135 | WindowCount mCount; 136 | }; 137 | 138 | } // ns streamulus 139 | -------------------------------------------------------------------------------- /inst/examples/D_sliding_window_function.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // D_sliding_window_function.cpp 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #include "../src/streamulus.h" 23 | #include "../src/sliding_window_library.h" 24 | #include "../src/sliding_window_func.h" 25 | 26 | #include 27 | 28 | // ------------------------------------------------------------------- 29 | // This example shows how to use a sliding window function. 30 | // The WindowSum function computes the sum of the last n items of a 31 | // stream of doubles (we set n=3). The function itself is defined 32 | // in sliding_window_library.h 33 | // 34 | // The output of the program is: 35 | // 36 | // ------------- TS <-- 0 ------------- 37 | // 0 38 | // ------------- TS <-- 1 ------------- 39 | // 1 40 | // ------------- TS <-- 2 ------------- 41 | // 3 42 | // ------------- TS <-- 3 ------------- 43 | // 6 44 | // ------------- TS <-- 4 ------------- 45 | // 9 46 | // ------------- TS <-- 0 ------------- 47 | // 7 48 | // ------------- TS <-- 1 ------------- 49 | // 5 50 | // ------------- TS <-- 2 ------------- 51 | // 3 52 | // ------------- TS <-- 3 ------------- 53 | // 6 54 | // ------------- TS <-- 4 ------------- 55 | // 9 56 | // ------------- TS <-- 0 ------------- 57 | // 7 58 | // ------------- TS <-- 1 ------------- 59 | // 5 60 | // ------------- TS <-- 2 ------------- 61 | // 3 62 | // ------------- TS <-- 3 ------------- 63 | // 6 64 | // ------------- TS <-- 4 ------------- 65 | // 9 66 | // ------------------------------------------------------------------- 67 | 68 | // Functor that prints whatever it gets. 69 | // Stremify is a stream function that prints every 70 | // element of a stream. 71 | struct print 72 | { 73 | template struct result; 74 | 75 | template 76 | struct result 77 | { 78 | typedef T type; 79 | }; 80 | 81 | template 82 | typename result::type 83 | operator()(const T& value) const 84 | { 85 | std::cout << value << std::endl; 86 | return value; 87 | } 88 | }; 89 | 90 | 91 | 92 | void sliding_window_function_example(); 93 | 94 | void sliding_window_function_example() 95 | { 96 | using namespace streamulus; 97 | 98 | InputStream::type ts = NewInputStream("TS", true /* verbose */); 99 | Streamulus engine; 100 | 101 | boost::proto::terminal::type window = {}; 102 | // Print the sum of the last three numbers: 103 | engine.Subscribe(Streamify(Streamify > >(window(3,ts)) )); 104 | 105 | for (int i=0; i<15; i++) 106 | InputStreamPut(ts, double(i % 5)); 107 | } 108 | 109 | #if defined(USE_MAIN) 110 | int main() 111 | { 112 | sliding_window_function_example(); 113 | return 0; 114 | } 115 | #endif 116 | -------------------------------------------------------------------------------- /src/hello.cpp: -------------------------------------------------------------------------------- 1 | // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- 2 | 3 | // adapted from Streamulus example 'A_hello_world.cpp' 4 | // 5 | // R Integration Copyright (C) 2014 - 2015 Dirk Eddelbuettel 6 | 7 | // 8 | // hello_world.cpp 9 | // 10 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 11 | // 12 | // This file is part of Streamulus. 13 | // 14 | // Streamulus is free software: you can redistribute it and/or modify 15 | // it under the terms of the GNU General Public License as published by 16 | // the Free Software Foundation, either version 3 of the License, or 17 | // (at your option) any later version. 18 | // 19 | // Streamulus is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU General Public License 25 | // along with Streamulus. If not, see . 26 | // 27 | 28 | 29 | // *************** Example A: Hello Stream! *************** 30 | // Below is a complete Streamulus program that receives 31 | // as input a stream of strings and greets each one 32 | // of them. 33 | // 34 | // The output of the program is below. The Streamulus InputStream 35 | // prints the values that arrive on the stream, and our program 36 | // prints the rest: 37 | // 38 | // ------------- Input Stream <-- World ------------- 39 | // Hello World! 40 | // ------------- Input Stream <-- London ------------- 41 | // Hello London! 42 | // ------------- Input Stream <-- Streamulus ------------- 43 | // Hello Streamulus! 44 | // 45 | // ******************************************************** 46 | 47 | #include // also includes Rcpp.h 48 | #include 49 | 50 | // print is a functor that prints whatever it gets. 51 | // Stremify is a stream function that prints every 52 | // element of a stream. 53 | struct print 54 | { 55 | template struct result; 56 | 57 | // Boost result-of protocol (not necessary in C++11) 58 | template 59 | struct result 60 | { 61 | typedef T type; 62 | }; 63 | 64 | // The actual function 65 | template 66 | typename result::type 67 | operator()(const T& value) const 68 | { 69 | StreamulusOut << value << std::endl; 70 | return value; 71 | } 72 | }; 73 | 74 | void hello_stream() 75 | { 76 | using namespace streamulus; 77 | 78 | // Define an input stream of strings, whose name is "Input Stream" 79 | InputStream::type s = NewInputStream("Input Stream", true /* verbose */); 80 | 81 | // Construct a streamulus instance 82 | Streamulus streamulus_engine; 83 | 84 | // Define some constants 85 | std::string hello("Hello "); 86 | std::string exc("!"); 87 | 88 | // For each element of the stream: 89 | // compute a greeting 90 | // print it 91 | // emit it into the output stream 92 | // 93 | 94 | 95 | streamulus_engine.Subscribe(Streamify(hello + s + exc)); 96 | 97 | // Insert data to the input stream 98 | InputStreamPut(s, "World"); 99 | InputStreamPut(s, "London"); 100 | InputStreamPut(s, "Streamulus"); 101 | } 102 | 103 | 104 | //' This is an example function illustrating Streamulus 105 | //' 106 | //' @title Print some hello messages 107 | //' @return An unconditional TRUE value 108 | //' @author Dirk Eddelbuettel 109 | //' @examples 110 | //' \dontrun{ 111 | //' helloStream() 112 | //' } 113 | // [[Rcpp::export]] 114 | bool helloStream() { 115 | hello_stream(); 116 | return true; 117 | } 118 | -------------------------------------------------------------------------------- /inst/examples/B_common_subexpression.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // B_common_subexpression.cpp 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | // *********** Example B: Common Subexpression *********** 23 | // This is an extension of Example A where the greeting 24 | // we compute for every element of the stream is needed 25 | // in more than one expression (outdegree > 1 in the graph). 26 | // 27 | // The greeting is computed and streamed through the Stremified 28 | // print functor as before, but we also capture a handle to 29 | // the output of print, which can be used in further expressions. 30 | // 31 | // The output of the program is: 32 | // 33 | // ------------- Input Stream <-- World ------------- 34 | // Hello World! 35 | // I said: Hello World! 36 | // All together now: Hello World!! 37 | // ------------- Input Stream <-- London ------------- 38 | // Hello London! 39 | // I said: Hello London! 40 | // All together now: Hello London!! 41 | // ------------- Input Stream <-- Streamulus ------------- 42 | // Hello Streamulus! 43 | // I said: Hello Streamulus! 44 | // All together now: Hello Streamulus!! 45 | // ******************************************************* 46 | 47 | #include "../src/streamulus.h" 48 | 49 | #include 50 | 51 | // The print functor from example A. 52 | struct print 53 | { 54 | template struct result; 55 | 56 | template 57 | struct result 58 | { 59 | typedef T type; 60 | }; 61 | 62 | template 63 | typename result::type 64 | operator()(const T& value) const 65 | { 66 | std::cout << value << std::endl; 67 | return value; 68 | } 69 | }; 70 | 71 | void common_subexpressions(); 72 | void common_subexpressions() 73 | { 74 | using namespace streamulus; 75 | 76 | InputStream::type s = NewInputStream("Input Stream", true /* verbose */); 77 | 78 | // Construct a streamulus instance 79 | Streamulus streamulus_engine; 80 | 81 | // Define some constants 82 | std::string hello("Hello "); 83 | std::string exc("!"); 84 | 85 | // For each element of the stream: 86 | // compute a greeting 87 | // print it 88 | // emit it into the output stream 89 | // 90 | // the output is assined to the 'greeting' variable, 91 | // which can be used in other streamulus expressions. 92 | // 93 | Subscription::type greeting = 94 | streamulus_engine.Subscribe(Streamify(hello + s + exc)); 95 | 96 | // Use the 'greeting' variable in other streamulus expressions. 97 | streamulus_engine.Subscribe(Streamify(std::string("I said: ") + greeting )); 98 | streamulus_engine.Subscribe(Streamify(std::string("All together now: ") + greeting + exc)); 99 | 100 | // Insert data to the input stream 101 | InputStreamPut(s, "World"); 102 | InputStreamPut(s, "London"); 103 | InputStreamPut(s, "Streamulus"); 104 | } 105 | 106 | #if defined(USE_MAIN) 107 | int main() 108 | { 109 | common_subexpressions(); 110 | return 0; 111 | } 112 | #endif 113 | 114 | -------------------------------------------------------------------------------- /src/sliding.cpp: -------------------------------------------------------------------------------- 1 | // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- 2 | 3 | // adapted from Streamulus example 'D_sliding_window_function.cpp' 4 | // 5 | // R Integration Copyright (C) 2015 Dirk Eddelbuettel 6 | 7 | // D_sliding_window_function.cpp 8 | // 9 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 10 | // 11 | // This file is part of Streamulus. 12 | // 13 | // Streamulus is free software: you can redistribute it and/or modify 14 | // it under the terms of the GNU General Public License as published by 15 | // the Free Software Foundation, either version 3 of the License, or 16 | // (at your option) any later version. 17 | // 18 | // Streamulus is distributed in the hope that it will be useful, 19 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | // GNU General Public License for more details. 22 | // 23 | // You should have received a copy of the GNU General Public License 24 | // along with Streamulus. If not, see . 25 | // 26 | 27 | #include // includes Rcpp.h as well 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | // ------------------------------------------------------------------- 34 | // This example shows how to use a sliding window function. 35 | // The WindowSum function computes the sum of the last n items of a 36 | // stream of doubles (we set n=3). The function itself is defined 37 | // in sliding_window_library.h 38 | // 39 | // The output of the program is: 40 | // 41 | // ------------- TS <-- 0 ------------- 42 | // 0 43 | // ------------- TS <-- 1 ------------- 44 | // 1 45 | // ------------- TS <-- 2 ------------- 46 | // 3 47 | // ------------- TS <-- 3 ------------- 48 | // 6 49 | // ------------- TS <-- 4 ------------- 50 | // 9 51 | // ------------- TS <-- 0 ------------- 52 | // 7 53 | // ------------- TS <-- 1 ------------- 54 | // 5 55 | // ------------- TS <-- 2 ------------- 56 | // 3 57 | // ------------- TS <-- 3 ------------- 58 | // 6 59 | // ------------- TS <-- 4 ------------- 60 | // 9 61 | // ------------- TS <-- 0 ------------- 62 | // 7 63 | // ------------- TS <-- 1 ------------- 64 | // 5 65 | // ------------- TS <-- 2 ------------- 66 | // 3 67 | // ------------- TS <-- 3 ------------- 68 | // 6 69 | // ------------- TS <-- 4 ------------- 70 | // 9 71 | // ------------------------------------------------------------------- 72 | 73 | // Functor that prints whatever it gets. 74 | // Stremify is a stream function that prints every 75 | // element of a stream. 76 | struct print 77 | { 78 | template struct result; 79 | 80 | template 81 | struct result 82 | { 83 | typedef T type; 84 | }; 85 | 86 | template 87 | typename result::type 88 | operator()(const T& value) const 89 | { 90 | StreamulusOut << value << std::endl; 91 | return value; 92 | } 93 | }; 94 | 95 | 96 | 97 | //void sliding_window_function_example(); 98 | 99 | void sliding_window_function_example() 100 | { 101 | using namespace streamulus; 102 | 103 | InputStream::type ts = NewInputStream("TS", true /* verbose */); 104 | Streamulus engine; 105 | 106 | boost::proto::terminal::type window = {}; 107 | // Print the sum of the last three numbers: 108 | engine.Subscribe(Streamify(Streamify > >(window(3,ts)) )); 109 | 110 | for (int i=0; i<15; i++) 111 | InputStreamPut(ts, double(i % 5)); 112 | } 113 | 114 | // #if defined(USE_MAIN) 115 | // int main() 116 | // { 117 | // sliding_window_function_example(); 118 | // return 0; 119 | // } 120 | // #endif 121 | 122 | 123 | //' This is an example function illustrating Streamulus 124 | //' 125 | //' @title Sliding window function example 126 | //' @return An unconditional TRUE value 127 | //' @author Dirk Eddelbuettel 128 | //' @examples 129 | //' \dontrun{ 130 | //' slidingWindow() 131 | //' } 132 | // [[Rcpp::export]] 133 | bool slidingWindow() { 134 | sliding_window_function_example(); 135 | return true; 136 | } 137 | -------------------------------------------------------------------------------- /inst/include/strop_base.h: -------------------------------------------------------------------------------- 1 | // 2 | // strop_base.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | namespace streamulus 25 | { 26 | class Engine; 27 | 28 | class StropBase 29 | { 30 | public: 31 | 32 | StropBase() 33 | { 34 | Init("unnamed"); 35 | } 36 | 37 | StropBase(const std::string& display_name) 38 | { 39 | Init(display_name); 40 | } 41 | 42 | private: 43 | void Init(const std::string& display_name) 44 | { 45 | mEngine = NULL; 46 | mVertexDescriptor = 0; 47 | mIsActive = false; 48 | mIsDeleted = false; 49 | mExternalReference = false; 50 | mDisplayName = display_name; 51 | } 52 | 53 | public: 54 | virtual ~StropBase() 55 | { 56 | } 57 | 58 | Graph::vertex_descriptor GetDescriptor() const 59 | { 60 | return mVertexDescriptor; 61 | } 62 | 63 | size_t GetTopSortIndex() const 64 | { 65 | return mTopSortIndex; 66 | } 67 | 68 | Engine* GetEngine() 69 | { 70 | return mEngine; 71 | } 72 | 73 | void SetGraph(Engine* engine, const Graph::vertex_descriptor& desc, size_t top_sort_index) 74 | { 75 | assert(mEngine==NULL || engine==NULL || engine == mEngine); 76 | mEngine = engine; 77 | mVertexDescriptor = desc; 78 | mTopSortIndex = top_sort_index; 79 | } 80 | 81 | inline bool IsActive() 82 | { 83 | return mIsActive; 84 | } 85 | 86 | void SetIsActive(bool isActive) 87 | { 88 | mIsActive = isActive; 89 | } 90 | 91 | const std::string& DisplayName() const 92 | { 93 | return mDisplayName; 94 | } 95 | 96 | void SetDisplayName(const std::string& name) 97 | { 98 | mDisplayName = name; 99 | } 100 | 101 | virtual void Work()=0; 102 | 103 | friend std::ostream& operator<<(std::ostream& os, const StropBase& strop) 104 | { 105 | return os << strop.DisplayName(); 106 | } 107 | 108 | void MarkAsDeleted() 109 | { 110 | mIsDeleted = true; 111 | } 112 | 113 | bool IsDeleted() 114 | { 115 | return mIsDeleted; 116 | } 117 | 118 | void AddExternalReference() 119 | { 120 | assert(!mExternalReference); 121 | mExternalReference = true; 122 | } 123 | 124 | bool RemoveExternalReference() 125 | { 126 | assert(mExternalReference); 127 | if (!mExternalReference) 128 | return false; 129 | mExternalReference = false; 130 | return true; 131 | } 132 | 133 | bool HasExternalReference() 134 | { 135 | return mExternalReference; 136 | } 137 | protected: 138 | 139 | Engine* mEngine; // no ownership. Do not delete. 140 | Graph::vertex_descriptor mVertexDescriptor; 141 | size_t mTopSortIndex; 142 | bool mIsActive; // is it in the "active" queue 143 | bool mIsDeleted; // Was deleted from the graph by the user (to be garbage collected). 144 | bool mExternalReference; // The user has a handle to this strop (so it can be used in future expressions). 145 | std::string mDisplayName; 146 | }; 147 | 148 | } // ns streamulus 149 | -------------------------------------------------------------------------------- /src/common.cpp: -------------------------------------------------------------------------------- 1 | // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- 2 | 3 | // adapted from Streamulus example 'B_common_subexpression.cpp' 4 | // 5 | // R Integration Copyright (C) 2015 Dirk Eddelbuettel 6 | 7 | // B_common_subexpression.cpp 8 | // 9 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 10 | // 11 | // This file is part of Streamulus. 12 | // 13 | // Streamulus is free software: you can redistribute it and/or modify 14 | // it under the terms of the GNU General Public License as published by 15 | // the Free Software Foundation, either version 3 of the License, or 16 | // (at your option) any later version. 17 | // 18 | // Streamulus is distributed in the hope that it will be useful, 19 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | // GNU General Public License for more details. 22 | // 23 | // You should have received a copy of the GNU General Public License 24 | // along with Streamulus. If not, see . 25 | // 26 | 27 | // *********** Example B: Common Subexpression *********** 28 | // This is an extension of Example A where the greeting 29 | // we compute for every element of the stream is needed 30 | // in more than one expression (outdegree > 1 in the graph). 31 | // 32 | // The greeting is computed and streamed through the Stremified 33 | // print functor as before, but we also capture a handle to 34 | // the output of print, which can be used in further expressions. 35 | // 36 | // The output of the program is: 37 | // 38 | // ------------- Input Stream <-- World ------------- 39 | // Hello World! 40 | // I said: Hello World! 41 | // All together now: Hello World!! 42 | // ------------- Input Stream <-- London ------------- 43 | // Hello London! 44 | // I said: Hello London! 45 | // All together now: Hello London!! 46 | // ------------- Input Stream <-- Streamulus ------------- 47 | // Hello Streamulus! 48 | // I said: Hello Streamulus! 49 | // All together now: Hello Streamulus!! 50 | // ******************************************************* 51 | 52 | #include // also includes Rcpp.h 53 | #include 54 | 55 | // The print functor from example A. 56 | struct print 57 | { 58 | template struct result; 59 | 60 | template 61 | struct result 62 | { 63 | typedef T type; 64 | }; 65 | 66 | template 67 | typename result::type 68 | operator()(const T& value) const 69 | { 70 | StreamulusOut << value << std::endl; 71 | return value; 72 | } 73 | }; 74 | 75 | void common_subexpressions() 76 | { 77 | using namespace streamulus; 78 | 79 | InputStream::type s = NewInputStream("Input Stream", true /* verbose */); 80 | 81 | // Construct a streamulus instance 82 | Streamulus streamulus_engine; 83 | 84 | // Define some constants 85 | std::string hello("Hello "); 86 | std::string exc("!"); 87 | 88 | // For each element of the stream: 89 | // compute a greeting 90 | // print it 91 | // emit it into the output stream 92 | // 93 | // the output is assined to the 'greeting' variable, 94 | // which can be used in other streamulus expressions. 95 | // 96 | Subscription::type greeting = 97 | streamulus_engine.Subscribe(Streamify(hello + s + exc)); 98 | 99 | // Use the 'greeting' variable in other streamulus expressions. 100 | streamulus_engine.Subscribe(Streamify(std::string("I said: ") + greeting )); 101 | streamulus_engine.Subscribe(Streamify(std::string("All together now: ") + greeting + exc)); 102 | 103 | // Insert data to the input stream 104 | InputStreamPut(s, "World"); 105 | InputStreamPut(s, "London"); 106 | InputStreamPut(s, "Streamulus"); 107 | } 108 | 109 | // #if defined(USE_MAIN) 110 | // int main() 111 | // { 112 | // common_subexpressions(); 113 | // return 0; 114 | // } 115 | // #endif 116 | 117 | 118 | //' This is an example function illustrating Streamulus 119 | //' 120 | //' @title Common 'greeting' carried across several expressions 121 | //' @return An unconditional TRUE value 122 | //' @author Dirk Eddelbuettel 123 | //' @examples 124 | //' \dontrun{ 125 | //' commonSubexpressions() 126 | //' } 127 | // [[Rcpp::export]] 128 | bool commonSubexpressions() { 129 | common_subexpressions(); 130 | return true; 131 | } 132 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2025-01-29 Dirk Eddelbuettel 2 | 3 | * DESCRIPTION (Version, Date): Release 0.1.4 4 | 5 | * .github/workflows/ci.yaml: Simplify via r-ci with included bootstrap 6 | 7 | 2024-10-27 Dirk Eddelbuettel 8 | 9 | * DESCRIPTION (Authors@R): Added 10 | 11 | 2024-07-16 Dirk Eddelbuettel 12 | 13 | * README.md: Switch some URLs from http to https 14 | 15 | 2024-05-23 Dirk Eddelbuettel 16 | 17 | * README.md: Use tinyverse.netlify.app for dependency badge 18 | 19 | 2024-04-08 Dirk Eddelbuettel 20 | 21 | * .github/workflows/ci.yaml (jobs): Update to actions/checkout@v4, 22 | add r-ci-setup actions 23 | 24 | 2023-04-17 Dirk Eddelbuettel 25 | 26 | * DESCRIPTION (Version, Date): Roll micro version and date 27 | 28 | * src/Makevars: No longer set a compilation standard 29 | 30 | 2022-11-18 Dirk Eddelbuettel 31 | 32 | * .github/workflows/ci.yaml (jobs): Update to actions/checkout@v3 33 | 34 | 2021-12-19 Dirk Eddelbuettel 35 | 36 | * README.md: Remove unused continuous integration artifact and badge 37 | 38 | 2021-01-12 Dirk Eddelbuettel 39 | 40 | * .github/workflows/ci.yaml: Add CI runner using r-ci 41 | * README.md: Add new badge 42 | 43 | 2020-05-25 Dirk Eddelbuettel 44 | 45 | * README.md: Add 'last commit' badge 46 | 47 | * .travis.yml: Switch to bionic and R 4.0.0 48 | 49 | 2019-07-11 Dirk Eddelbuettel 50 | 51 | * DESCRIPTION (Author): Use name without email as in other packages 52 | 53 | 2019-02-24 Dirk Eddelbuettel 54 | 55 | * DESCRIPTION (Version, Date): Release 0.1.3 56 | 57 | * src/common.cpp: Wrap '\dontrun{}' around example 58 | * src/movavg.cpp: Idem 59 | * src/hello.cpp: Idem 60 | * src/sliding.cpp: Idem 61 | 62 | 2019-01-05 Dirk Eddelbuettel 63 | 64 | * DESCRIPTION (Version, Date): Release 0.1.2 65 | 66 | 2018-12-29 Dirk Eddelbuettel 67 | 68 | * inst/include/grammar.h: Convert from CRLF to CR 69 | * inst/include/stream.h: Idem 70 | * inst/include/strop.h: Idem 71 | * inst/include/strop_func.h: Idem 72 | 73 | * inst/include/operators.h: Added final newline 74 | * inst/include/stream_base.h: Idem 75 | * inst/include/strop_sliding_window.h: Idem 76 | * inst/include/strop_stream_producer.h: Idem 77 | 78 | 2018-12-22 Dirk Eddelbuettel 79 | 80 | * inst/include/engine.h (streamulus): Comment-out optional use of 81 | boost::proto::display_expr which upsets the linker under Boost 1.69 82 | 83 | * src/RcppExports.cpp: Regenerated to provide symbol registration 84 | * R/RcppExports.R: Idem 85 | * NAMESPACE: Add .registration=TRUE to useDynLib() 86 | 87 | 2017-08-26 Dirk Eddelbuettel 88 | 89 | * .travis.yml (before_install): Use https for curl fetch 90 | 91 | 2016-08-05 Dirk Eddelbuettel 92 | 93 | * DESCRIPTION (Version): New release 0.1.1 94 | 95 | * DESCRIPTION (URL): Added 96 | (BugReports): Added 97 | 98 | * src/Makevars (CXX_STD): Compiled as a C++11 project 99 | 100 | * .travis.yml: Switch to using run.sh for Travis CI 101 | 102 | 2015-02-01 Dirk Eddelbuettel 103 | 104 | * inst/include/RcppStreams.h: Adding as first step towards a 105 | RcppStreams header wrapper leaving Streamulus as unmodified as possible 106 | 107 | * inst/include/composed_func.: Use StreamulusOut define for output 108 | * inst/include/engine.h: Ditto 109 | * inst/include/streamulus.h: Ditto 110 | * inst/include/strop_data_source.h: Ditto 111 | * inst/include/transforms.h: Ditto 112 | 113 | * src/hello.cpp: Some normalization with Streamulus 114 | * src/common.cpp: Ditto 115 | * src/movavg.cpp: Ditto 116 | * src/sliding.cpp: Ditto 117 | 118 | 2015-01-31 Dirk Eddelbuettel 119 | 120 | * DESCRIPTION: Wrapped up as release 0.1.0 121 | 122 | * src/*.cpp: Add simple example to each roxygen documentation entry 123 | * man/*.Rd: Ditto 124 | 125 | 2015-01-30 Dirk Eddelbuettel 126 | 127 | * src/sliding.cpp: New function slidingWindows() added based on 128 | Streamulus example D* 129 | * man/slidingWindow.Rd: Ditto 130 | 131 | * src/common.cpp" New function commonSubexpressions() added based on 132 | Streamulus example B* 133 | 134 | * inst/tests/GNUmakefile: Renamed from Makefile to lease R CMD check 135 | * inst/examples/GNUmakefile: Ditto 136 | 137 | 2015-01-28 Dirk Eddelbuettel 138 | 139 | * src/movavg.cpp: Fully restore second example disabled for i/o tests 140 | * src/hello.cpp: Simpler (void) interface to first example 141 | 142 | 2015-01-05 Dirk Eddelbuettel 143 | 144 | * .travis.yml: Activated now that Boost Fusion and Graph are in BH 145 | 146 | 2015-01-02 Dirk Eddelbuettel 147 | 148 | * inst/include/engine.h: Supply Rcpp::Rcout as an argument to 149 | boost::proto::display_expr [thanks, @dcdillon !!] which suppresses 150 | default use of std::cout about which R CMD check complains loudly 151 | 152 | * .travis.yml: First steps towards TravisCI integration -- not yet 153 | successful as we need more pieces from Boost than Travis has 154 | 155 | 2014-08-09 Dirk Eddelbuettel 156 | 157 | * inst/include/*: Various unsuccessful attempts to suppress std::cout 158 | 159 | * src/hello.cpp: Add basic roxygen documentation 160 | * src/movavg.cpp: Ditto 161 | 162 | * inst/include/*: Moved headers from src/ to be used by other packages 163 | 164 | * inst/doc/*: Moved from doc/ to ensure installation in user package 165 | * inst/examples/*: Moved from examples/ to ensure installation in pkg 166 | 167 | * src/hello.cpp: First example based on Streamulus example A* 168 | * src/movavg.cpp: Second example based on Streamulus example C* 169 | 170 | * DESCRIPTION: Basic package infrastructure 171 | * NAMESPACE: Ditto 172 | * src/Makevars: Ditto 173 | 174 | 2014-08-09 Dirk Eddelbuettel 175 | 176 | * src/engine.h: Do not unconditionally write out graph file 177 | 178 | * tests/tests.cpp: Added outer wrapper 179 | * tests/Makefile: Added as well 180 | 181 | * examples/Makefile: Added 182 | 183 | * exampples/*.cpp: Protect main() behind a define in all examples 184 | 185 | * src/transforms.h: Comment-out unused variable for g++ -pedantic 186 | * src/engine.h: Reorder initialization for g++ -pedantic 187 | -------------------------------------------------------------------------------- /inst/include/streamify.h: -------------------------------------------------------------------------------- 1 | // 2 | // streamify.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | namespace streamulus 27 | { 28 | 29 | namespace bp = boost::proto; 30 | 31 | // Streamify template - turns a function object into a streamulus function. 32 | // 33 | // There are two variants for Streamify - one that gets a function object 34 | // and copies it, and the other which gets the type of the function as a 35 | // template parameter and constructs an object of this type. 36 | // 37 | // Both variants are useful - the first is more general because the function 38 | // object does not need to be constructible without parameters. The second 39 | // can be invoked more concisely when the function is constructible in this way. 40 | // 41 | 42 | 43 | // From object: Copies the function object into a terminal. 44 | template 45 | typename bp::terminal::type const 46 | Streamify(F const& f) 47 | { 48 | typename bp::terminal::type that = {f}; 49 | return that; 50 | } 51 | 52 | // From type: Constructs the function object 53 | // We have one Streamify function for each arity of F. 54 | template 55 | typename bp::result_of::make_expr< 56 | bp::tag::function // Tag type 57 | , F // First child (by value) 58 | , A1 const & // Second child (by reference) 59 | >::type const 60 | Streamify(const A1& a1) 61 | { 62 | return bp::make_expr( 63 | F() // First child (by value) 64 | , boost::ref(a1) // Second child (by reference) 65 | ); 66 | } 67 | 68 | template 69 | typename bp::result_of::make_expr< 70 | bp::tag::function // Tag type 71 | , F // First child (by value) 72 | , A1 const & // Second child (by reference) 73 | , A2 const & // Third child (by reference) 74 | >::type const 75 | Streamify(const A1& a1, const A2& a2) 76 | { 77 | return bp::make_expr( 78 | F() // First child (by value) 79 | , boost::ref(a1) // Second child (by reference) 80 | , boost::ref(a2) // Third child (by reference) 81 | ); 82 | } 83 | 84 | template 85 | typename bp::result_of::make_expr< 86 | bp::tag::function // Tag type 87 | , F // First child (by value) 88 | , A1 const & // Second child (by reference) 89 | , A2 const & // Third child (by reference) 90 | , A3 const & // Fourth child (by reference) 91 | >::type const 92 | Streamify(const A1& a1, const A2& a2, const A3& a3) 93 | { 94 | return bp::make_expr( 95 | F() // First child (by value) 96 | , boost::ref(a1) // Second child (by reference) 97 | , boost::ref(a2) // Third child (by reference) 98 | , boost::ref(a3) // Fourth child (by reference) 99 | ); 100 | } 101 | 102 | template 103 | typename bp::result_of::make_expr< 104 | bp::tag::function // Tag type 105 | , F // First child (by value) 106 | , A1 const & // Second child (by reference) 107 | , A2 const & // Third child (by reference) 108 | , A3 const & // Fourth child (by reference) 109 | , A4 const & // Fifth child (by reference) 110 | >::type const 111 | Streamify(const A1& a1, const A2& a2, const A3& a3, const A4& a4) 112 | { 113 | return bp::make_expr( 114 | F() // First child (by value) 115 | , boost::ref(a1) // Second child (by reference) 116 | , boost::ref(a2) // Third child (by reference) 117 | , boost::ref(a3) // Fourth child (by reference) 118 | , boost::ref(a4) // Fifth child (by reference) 119 | ); 120 | } 121 | 122 | template 123 | typename bp::result_of::make_expr< 124 | bp::tag::function // Tag type 125 | , F // First child (by value) 126 | , A1 const & // Second child (by reference) 127 | , A2 const & // Third child (by reference) 128 | , A3 const & // Fourth child (by reference) 129 | , A4 const & // Fifth child (by reference) 130 | , A5 const & // Sixth child (by reference) 131 | >::type const 132 | Streamify(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) 133 | { 134 | return bp::make_expr( 135 | F() // First child (by value) 136 | , boost::ref(a1) // Second child (by reference) 137 | , boost::ref(a2) // Third child (by reference) 138 | , boost::ref(a3) // Fourth child (by reference) 139 | , boost::ref(a4) // Fifth child (by reference) 140 | , boost::ref(a5) // Sixth child (by reference) 141 | ); 142 | } 143 | 144 | } // ns streamulus 145 | -------------------------------------------------------------------------------- /inst/examples/C_user_defined_functions_and_filters.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // C_user_defined_functions_and_filters.cpp 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #include "../src/streamulus.h" 23 | 24 | #include 25 | 26 | // ------------------------------------------------------------------- 27 | // This example implements an algorithm to detect crossings of two 28 | // moving averages of a time series. 29 | // The input is given as {time, value} pairs. 30 | // We have a slow-decaying moving average and a fast-decaying one. 31 | // When they cross we issue an alert (in this case print to the 32 | // screen). We distinguish between Death Crosses (where the slow 33 | // mavg crosses the fast one from below, so the time series is 34 | // decreasing) and Golden Crosses (where it crosses from above, 35 | // so the time series is increasing). 36 | // 37 | // The example demonstrates expressions using user-defined functions, 38 | // * with and without filters 39 | // * Streamified by type or by object. 40 | // 41 | // The output of the program is: 42 | // 43 | // ------------- TS <-- {0,0} ------------- 44 | // Slow Mavg = 0 45 | // Death cross detected! 46 | // Fast Mavg = 0 47 | // ------------- TS <-- {1,1} ------------- 48 | // Slow Mavg = 0.632121 49 | // Golden cross detected! 50 | // Fast Mavg = 0.999955 51 | // ------------- TS <-- {2,2} ------------- 52 | // Slow Mavg = 1.49679 53 | // Fast Mavg = 1.99995 54 | // ------------- TS <-- {3,3} ------------- 55 | // Slow Mavg = 2.447 56 | // Fast Mavg = 2.99995 57 | // ------------- TS <-- {4,4} ------------- 58 | // Slow Mavg = 3.42868 59 | // Fast Mavg = 3.99995 60 | // ------------- TS <-- {5,0} ------------- 61 | // Slow Mavg = 1.26134 62 | // Death cross detected! 63 | // Fast Mavg = 0.000181598 64 | // ------------- TS <-- {6,1} ------------- 65 | // Slow Mavg = 1.09614 66 | // Fast Mavg = 0.999955 67 | // ------------- TS <-- {7,2} ------------- 68 | // Slow Mavg = 1.66749 69 | // Golden cross detected! 70 | // Fast Mavg = 1.99995 71 | // ------------- TS <-- {8,3} ------------- 72 | // Slow Mavg = 2.5098 73 | // Fast Mavg = 2.99995 74 | // ------------- TS <-- {9,4} ------------- 75 | // Slow Mavg = 3.45178 76 | // Fast Mavg = 3.99995 77 | // ------------- TS <-- {10,0} ------------- 78 | // Slow Mavg = 1.26984 79 | // Death cross detected! 80 | // Fast Mavg = 0.000181598 81 | // ------------- TS <-- {11,1} ------------- 82 | // Slow Mavg = 1.09927 83 | // Fast Mavg = 0.999955 84 | // ------------- TS <-- {12,2} ------------- 85 | // Slow Mavg = 1.66864 86 | // Golden cross detected! 87 | // Fast Mavg = 1.99995 88 | // ------------- TS <-- {13,3} ------------- 89 | // Slow Mavg = 2.51022 90 | // Fast Mavg = 2.99995 91 | // ------------- TS <-- {14,4} ------------- 92 | // Slow Mavg = 3.45194 93 | // Fast Mavg = 3.99995 94 | // 95 | // -------------------------------------------------------------------- 96 | 97 | // time-value pair 98 | struct TimeValue 99 | { 100 | TimeValue() 101 | : time(0) 102 | , value(0) 103 | { 104 | } 105 | 106 | TimeValue(clock_t t, double v) 107 | : time(t) 108 | , value(v) 109 | { 110 | } 111 | 112 | friend std::ostream& operator<<(std::ostream& os, const TimeValue& tv) 113 | { 114 | return os << "{" << tv.time << "," << tv.value << "}"; 115 | } 116 | 117 | clock_t time; 118 | double value; 119 | }; 120 | 121 | // Exponentially decaying moving average 122 | class Mavg 123 | { 124 | public: 125 | 126 | Mavg(int decay_factor) 127 | : mFirst(true) 128 | , mDecayFactor(decay_factor) 129 | , mMavg(0) 130 | { 131 | } 132 | 133 | template 134 | struct result 135 | { 136 | typedef double type; 137 | }; 138 | 139 | double operator()(const TimeValue& tick) 140 | { 141 | if (! mFirst) 142 | { 143 | double alpha = 1-1/exp(mDecayFactor*(tick.time-mPrevTime)); 144 | mMavg += alpha*(tick.value - mMavg); 145 | mPrevTime = tick.time; 146 | } 147 | else 148 | { 149 | mMavg = tick.value; 150 | mPrevTime = tick.time; 151 | mFirst = false; 152 | } 153 | return mMavg; 154 | } 155 | 156 | private: 157 | clock_t mPrevTime; 158 | bool mFirst; 159 | int mDecayFactor; 160 | double mMavg; 161 | }; 162 | 163 | // Remove consecutive repetitions from a stream. 164 | template 165 | class unique 166 | { 167 | public: 168 | 169 | unique() 170 | : mFirst(true) 171 | { 172 | } 173 | 174 | template 175 | struct result 176 | { 177 | typedef T type; 178 | }; 179 | 180 | boost::optional operator()(const T& value) 181 | { 182 | if (mFirst || (value != mPrev)) 183 | { 184 | mFirst = false; 185 | return mPrev = value; 186 | } 187 | return boost::none; 188 | } 189 | 190 | private: 191 | bool mFirst; 192 | T mPrev; 193 | }; 194 | 195 | 196 | // Print an alert when a cross comes. Value indicates 197 | // the type of the cross. 198 | struct cross_alert 199 | { 200 | template 201 | struct result 202 | { 203 | typedef bool type; 204 | }; 205 | 206 | 207 | bool operator()(const bool is_golden_cross) 208 | { 209 | if (is_golden_cross) 210 | std::cout << "Golden cross detected!" << std::endl; 211 | else 212 | std::cout << "Death cross detected!" << std::endl; 213 | 214 | return is_golden_cross; 215 | } 216 | 217 | }; 218 | 219 | // Functor that prints whatever it gets. 220 | // Stremify is a stream function that prints every 221 | // element of a stream. 222 | struct print 223 | { 224 | template struct result; 225 | 226 | template 227 | struct result 228 | { 229 | typedef T type; 230 | }; 231 | 232 | template 233 | typename result::type 234 | operator()(const T& value) const 235 | { 236 | std::cout << value << std::endl; 237 | return value; 238 | } 239 | }; 240 | 241 | 242 | // Return whatever you got as a string. This is useful 243 | // for printing sub-expression results within a string 244 | // (converting to string allows + with other strings). 245 | struct as_string 246 | { 247 | template struct result; 248 | 249 | template 250 | struct result 251 | { 252 | typedef std::string type; 253 | }; 254 | 255 | template 256 | typename result::type 257 | operator()(const T& value) const 258 | { 259 | std::stringstream ss; 260 | ss << value; 261 | return ss.str(); 262 | } 263 | }; 264 | 265 | void cross_alert_example(); 266 | 267 | void cross_alert_example() 268 | { 269 | using namespace streamulus; 270 | 271 | InputStream::type ts = NewInputStream("TS", true /* verbose */); 272 | Streamulus engine; 273 | 274 | // The moving averages are streamified from the function objects. 275 | Mavg mavg1(1); 276 | Mavg mavg10(10); 277 | 278 | Subscription::type slow = engine.Subscribe(Streamify(mavg1)(ts)); 279 | Subscription::type fast = engine.Subscribe(Streamify(mavg10)(ts)); 280 | 281 | // print and cross_alert are streamified from the types (this work because they 282 | // can be default constructed). 283 | 284 | // Print the moving averages: 285 | engine.Subscribe(Streamify(std::string("Slow Mavg = ") + Streamify(slow))); 286 | engine.Subscribe(Streamify(std::string("Fast Mavg = ") + Streamify(fast))); 287 | 288 | // The cross detection expression: 289 | engine.Subscribe(Streamify( Streamify >(slow < fast))); 290 | 291 | for (int i=0; i<15; i++) 292 | InputStreamPut(ts, TimeValue(i, i % 5)); 293 | } 294 | 295 | #if defined(USE_MAIN) 296 | int main() 297 | { 298 | cross_alert_example(); 299 | return 0; 300 | } 301 | #endif 302 | -------------------------------------------------------------------------------- /src/movavg.cpp: -------------------------------------------------------------------------------- 1 | // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- 2 | 3 | // adapted from Streamulus example 'C_user_defined_functions_and_filters.cpp' 4 | // 5 | // R Integration Copyright (C) 2014 - 2015 Dirk Eddelbuettel 6 | 7 | 8 | // C_user_defined_functions_and_filters.cpp 9 | // 10 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 11 | // 12 | // This file is part of Streamulus. 13 | // 14 | // Streamulus is free software: you can redistribute it and/or modify 15 | // it under the terms of the GNU General Public License as published by 16 | // the Free Software Foundation, either version 3 of the License, or 17 | // (at your option) any later version. 18 | // 19 | // Streamulus is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU General Public License 25 | // along with Streamulus. If not, see . 26 | // 27 | 28 | #include // also includes Rcpp.h 29 | #include 30 | 31 | // ------------------------------------------------------------------- 32 | // This example implements an algorithm to detect crossings of two 33 | // moving averages of a time series. 34 | // The input is given as {time, value} pairs. 35 | // We have a slow-decaying moving average and a fast-decaying one. 36 | // When they cross we issue an alert (in this case print to the 37 | // screen). We distinguish between Death Crosses (where the slow 38 | // mavg crosses the fast one from below, so the time series is 39 | // decreasing) and Golden Crosses (where it crosses from above, 40 | // so the time series is increasing). 41 | // 42 | // The example demonstrates expressions using user-defined functions, 43 | // * with and without filters 44 | // * Streamified by type or by object. 45 | // 46 | // The output of the program is: 47 | // 48 | // ------------- TS <-- {0,0} ------------- 49 | // Slow Mavg = 0 50 | // Death cross detected! 51 | // Fast Mavg = 0 52 | // ------------- TS <-- {1,1} ------------- 53 | // Slow Mavg = 0.632121 54 | // Golden cross detected! 55 | // Fast Mavg = 0.999955 56 | // ------------- TS <-- {2,2} ------------- 57 | // Slow Mavg = 1.49679 58 | // Fast Mavg = 1.99995 59 | // ------------- TS <-- {3,3} ------------- 60 | // Slow Mavg = 2.447 61 | // Fast Mavg = 2.99995 62 | // ------------- TS <-- {4,4} ------------- 63 | // Slow Mavg = 3.42868 64 | // Fast Mavg = 3.99995 65 | // ------------- TS <-- {5,0} ------------- 66 | // Slow Mavg = 1.26134 67 | // Death cross detected! 68 | // Fast Mavg = 0.000181598 69 | // ------------- TS <-- {6,1} ------------- 70 | // Slow Mavg = 1.09614 71 | // Fast Mavg = 0.999955 72 | // ------------- TS <-- {7,2} ------------- 73 | // Slow Mavg = 1.66749 74 | // Golden cross detected! 75 | // Fast Mavg = 1.99995 76 | // ------------- TS <-- {8,3} ------------- 77 | // Slow Mavg = 2.5098 78 | // Fast Mavg = 2.99995 79 | // ------------- TS <-- {9,4} ------------- 80 | // Slow Mavg = 3.45178 81 | // Fast Mavg = 3.99995 82 | // ------------- TS <-- {10,0} ------------- 83 | // Slow Mavg = 1.26984 84 | // Death cross detected! 85 | // Fast Mavg = 0.000181598 86 | // ------------- TS <-- {11,1} ------------- 87 | // Slow Mavg = 1.09927 88 | // Fast Mavg = 0.999955 89 | // ------------- TS <-- {12,2} ------------- 90 | // Slow Mavg = 1.66864 91 | // Golden cross detected! 92 | // Fast Mavg = 1.99995 93 | // ------------- TS <-- {13,3} ------------- 94 | // Slow Mavg = 2.51022 95 | // Fast Mavg = 2.99995 96 | // ------------- TS <-- {14,4} ------------- 97 | // Slow Mavg = 3.45194 98 | // Fast Mavg = 3.99995 99 | // 100 | // -------------------------------------------------------------------- 101 | 102 | 103 | // time-value pair 104 | struct TimeValue 105 | { 106 | TimeValue() 107 | : time(0) 108 | , value(0) 109 | { 110 | } 111 | 112 | TimeValue(clock_t t, double v) 113 | : time(t) 114 | , value(v) 115 | { 116 | } 117 | 118 | friend std::ostream& operator<<(std::ostream& os, const TimeValue& tv) 119 | { 120 | return os << "{" << tv.time << "," << tv.value << "}"; 121 | } 122 | 123 | //clock_t time; 124 | double time; 125 | double value; 126 | }; 127 | 128 | // Exponentially decaying moving average 129 | class Mavg 130 | { 131 | public: 132 | 133 | Mavg(int decay_factor) 134 | : mFirst(true) 135 | , mDecayFactor(decay_factor) 136 | , mMavg(0) 137 | { 138 | } 139 | 140 | template 141 | struct result 142 | { 143 | typedef double type; 144 | }; 145 | 146 | double operator()(const TimeValue& tick) 147 | { 148 | if (! mFirst) 149 | { 150 | double alpha = 1-1/exp(mDecayFactor*(tick.time-mPrevTime)); 151 | mMavg += alpha*(tick.value - mMavg); 152 | mPrevTime = tick.time; 153 | } 154 | else 155 | { 156 | mMavg = tick.value; 157 | mPrevTime = tick.time; 158 | mFirst = false; 159 | } 160 | return mMavg; 161 | } 162 | 163 | private: 164 | /*clock_t*/ double mPrevTime; 165 | bool mFirst; 166 | int mDecayFactor; 167 | double mMavg; 168 | }; 169 | 170 | // Remove consecutive repetitions from a stream. 171 | template 172 | class unique 173 | { 174 | public: 175 | 176 | unique() 177 | : mFirst(true) 178 | { 179 | } 180 | 181 | template 182 | struct result 183 | { 184 | typedef T type; 185 | }; 186 | 187 | boost::optional operator()(const T& value) 188 | { 189 | if (mFirst || (value != mPrev)) 190 | { 191 | mFirst = false; 192 | return mPrev = value; 193 | } 194 | return boost::none; 195 | } 196 | 197 | private: 198 | bool mFirst; 199 | T mPrev; 200 | }; 201 | 202 | // Print an alert when a cross comes. Value indicates 203 | // the type of the cross. 204 | struct cross_alert 205 | { 206 | template 207 | struct result 208 | { 209 | typedef bool type; 210 | }; 211 | 212 | 213 | bool operator()(const bool is_golden_cross) 214 | { 215 | if (is_golden_cross) 216 | StreamulusOut << "Golden cross detected!" << std::endl; 217 | else 218 | StreamulusOut << "Death cross detected!" << std::endl; 219 | 220 | return is_golden_cross; 221 | } 222 | 223 | }; 224 | 225 | // Functor that prints whatever it gets. 226 | // Stremify is a stream function that prints every 227 | // element of a stream. 228 | struct print { 229 | template struct result; 230 | 231 | template 232 | struct result { 233 | typedef T type; 234 | }; 235 | 236 | template 237 | typename result::type 238 | operator()(const T& value) const { 239 | StreamulusOut << value << std::endl; 240 | return value; 241 | } 242 | }; 243 | 244 | 245 | // Return whatever you got as a string. This is useful 246 | // for printing sub-expression results within a string 247 | // (converting to string allows + with other strings). 248 | struct as_string { 249 | template struct result; 250 | 251 | template 252 | struct result { 253 | typedef std::string type; 254 | }; 255 | 256 | template 257 | typename result::type 258 | operator()(const T& value) const { 259 | std::stringstream ss; 260 | ss << value; 261 | return ss.str(); 262 | } 263 | }; 264 | 265 | void cross_alert_example(int f1, int f2) { 266 | using namespace streamulus; 267 | 268 | InputStream::type ts = NewInputStream("TS", false /* verbose */); 269 | Streamulus engine; 270 | 271 | // The moving averages are streamified from the function objects. 272 | Mavg mavg1(f1); 273 | Mavg mavg10(f2); 274 | 275 | Subscription::type slow = engine.Subscribe(Streamify(mavg1)(ts)); 276 | Subscription::type fast = engine.Subscribe(Streamify(mavg10)(ts)); 277 | 278 | // print and cross_alert are streamified from the types (this work because they 279 | // can be default constructed). 280 | 281 | // Print the moving averages: 282 | engine.Subscribe(Streamify(std::string("Slow Mavg = ") + Streamify(slow))); 283 | engine.Subscribe(Streamify(std::string("Fast Mavg = ") + Streamify(fast))); 284 | 285 | // The cross detection expression: 286 | engine.Subscribe(Streamify( Streamify >(slow < fast))); 287 | 288 | for (int i=0; i<15; i++) { 289 | double t = (i % 2) ? i/2.0 : (i-1)/2.0 + 0.125; 290 | InputStreamPut(ts, TimeValue(t, i % 5)); 291 | } 292 | } 293 | 294 | //' This is an example function illustrating Streamulus 295 | //' 296 | //' @title Alert for cross of two moving averages 297 | //' @param f1 Parameter for the slower exponential moving average 298 | //' @param f2 Parameter for the faster exponential moving average 299 | //' @return An unconditional TRUE value 300 | //' @author Dirk Eddelbuettel 301 | //' @examples 302 | //' \dontrun{ 303 | //' crossAlert(10,20) 304 | //' } 305 | // [[Rcpp::export]] 306 | bool crossAlert(int f1, int f2) { 307 | cross_alert_example(f1, f2); 308 | return true; 309 | } 310 | -------------------------------------------------------------------------------- /inst/include/strop_func.h: -------------------------------------------------------------------------------- 1 | // 2 | // strop_func.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | 25 | #include 26 | 27 | #include 28 | 29 | #include "strop.h" 30 | 31 | namespace streamulus 32 | { 33 | template 34 | class FuncBase : public Strop 35 | { 36 | public: 37 | typedef F function_type; 38 | 39 | FuncBase(const F& f) 40 | : mFunction(f) 41 | , mInputExists(false) 42 | { 43 | std::stringstream ss; 44 | ss << "Func_" << "F"; 45 | Strop::SetDisplayName(ss.str()); 46 | } 47 | 48 | inline const F& GetFunction() const 49 | { 50 | return mFunction; 51 | } 52 | 53 | protected: 54 | F mFunction; 55 | bool mInputExists; 56 | }; 57 | 58 | 59 | template::type> 61 | class Func0 : public FuncBase 62 | { 63 | public: 64 | 65 | typedef FuncBase BaseType; 66 | 67 | Func0(const F& f) 68 | : BaseType(f) 69 | { 70 | } 71 | 72 | virtual void Work() 73 | { 74 | R value = BaseType::mFunction(); 75 | StropStreamProducer::Output(value); 76 | } 77 | }; 78 | 79 | 80 | template::type> 83 | class Func1 : public FuncBase 84 | { 85 | public: 86 | 87 | typedef FuncBase BaseType; 88 | 89 | Func1(const F& f) 90 | : BaseType(f) 91 | { 92 | } 93 | 94 | virtual void Work() 95 | { 96 | Stream* const input1(Strop::template Input()); 97 | 98 | BaseType::mInputExists |= input1->IsValid(); 99 | 100 | if (BaseType::mInputExists) 101 | { 102 | while (input1->HasMore()) 103 | { 104 | const A1& a1(input1->Current()); 105 | boost::optional res = BaseType::mFunction(a1); 106 | if (res) 107 | StropStreamProducer::Output(*res); 108 | } 109 | } 110 | } 111 | }; 112 | 113 | template::type> 117 | class Func2 : public FuncBase 118 | { 119 | public: 120 | 121 | typedef FuncBase BaseType; 122 | 123 | Func2(const F& f) 124 | : BaseType(f) 125 | { 126 | } 127 | 128 | virtual void Work() 129 | { 130 | Stream* const input1(Strop::template Input()); 131 | Stream* const input2(Strop::template Input()); 132 | 133 | BaseType::mInputExists |= (input1->IsValid() && input2->IsValid()); 134 | 135 | if (BaseType::mInputExists) 136 | { 137 | while (input1->HasMore() || 138 | input2->HasMore() ) 139 | { 140 | const A1& a1(input1->Current()); 141 | const A2& a2(input2->Current()); 142 | 143 | boost::optional res = BaseType::mFunction(a1,a2); 144 | if (res) 145 | StropStreamProducer::Output(*res); 146 | } 147 | } 148 | } 149 | }; 150 | 151 | template::type> 156 | class Func3 : public FuncBase 157 | { 158 | public: 159 | 160 | typedef FuncBase BaseType; 161 | 162 | Func3(const F& f) 163 | : BaseType(f) 164 | { 165 | } 166 | 167 | virtual void Work() 168 | { 169 | Stream* const input1(Strop::template Input()); 170 | Stream* const input2(Strop::template Input()); 171 | Stream* const input3(Strop::template Input()); 172 | 173 | BaseType::mInputExists |= (input1->IsValid() && input2->IsValid() && input3->IsValid()); 174 | 175 | if (BaseType::mInputExists) 176 | { 177 | while (input1->HasMore() || 178 | input2->HasMore() || 179 | input3->HasMore() ) 180 | { 181 | const A1& a1(input1->Current()); 182 | const A2& a2(input2->Current()); 183 | const A3& a3(input3->Current()); 184 | 185 | boost::optional res = BaseType::mFunction(a1,a2,a3); 186 | if (res) 187 | StropStreamProducer::Output(*res); 188 | } 189 | } 190 | } 191 | }; 192 | 193 | template::type> 199 | class Func4 : public FuncBase 200 | { 201 | public: 202 | 203 | typedef FuncBase BaseType; 204 | 205 | Func4(const F& f) 206 | : BaseType(f) 207 | { 208 | } 209 | 210 | virtual void Work() 211 | { 212 | Stream* const input1(Strop::template Input()); 213 | Stream* const input2(Strop::template Input()); 214 | Stream* const input3(Strop::template Input()); 215 | Stream* const input4(Strop::template Input()); 216 | 217 | BaseType::mInputExists |= 218 | (input1->IsValid() && input2->IsValid() && input3->IsValid() && input4->IsValid()); 219 | 220 | if (BaseType::mInputExists) 221 | { 222 | while (input1->HasMore() || 223 | input2->HasMore() || 224 | input3->HasMore() || 225 | input4->HasMore() ) 226 | { 227 | const A1& a1(input1->Current()); 228 | const A2& a2(input2->Current()); 229 | const A3& a3(input3->Current()); 230 | const A4& a4(input4->Current()); 231 | 232 | boost::optional res = BaseType::mFunction(a1,a2,a3,a4); 233 | if (res) 234 | StropStreamProducer::Output(*res); 235 | } 236 | } 237 | } 238 | }; 239 | 240 | template::type> 247 | class Func5 : public FuncBase 248 | { 249 | public: 250 | 251 | typedef FuncBase BaseType; 252 | 253 | Func5(const F& f) 254 | : BaseType(f) 255 | { 256 | } 257 | 258 | virtual void Work() 259 | { 260 | Stream* const input1(Strop::template Input()); 261 | Stream* const input2(Strop::template Input()); 262 | Stream* const input3(Strop::template Input()); 263 | Stream* const input4(Strop::template Input()); 264 | Stream* const input5(Strop::template Input()); 265 | 266 | BaseType::mInputExists |= 267 | (input1->IsValid() && input2->IsValid() && input3->IsValid() && input4->IsValid() && input5->IsValid()); 268 | 269 | if (BaseType::mInputExists) 270 | { 271 | while (input1->HasMore() || 272 | input2->HasMore() || 273 | input3->HasMore() || 274 | input4->HasMore() || 275 | input5->HasMore() ) 276 | { 277 | const A1& a1(input1->Current()); 278 | const A2& a2(input2->Current()); 279 | const A3& a3(input3->Current()); 280 | const A4& a4(input4->Current()); 281 | const A5& a5(input5->Current()); 282 | 283 | boost::optional res = BaseType::mFunction(a1,a2,a3,a4,a5); 284 | if (res) 285 | StropStreamProducer::Output(*res); 286 | } 287 | } 288 | } 289 | }; 290 | 291 | 292 | } // ns streamulus 293 | -------------------------------------------------------------------------------- /inst/tests/operator_subscribe_test.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // operator_subscribe_tests.cpp 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #include 23 | 24 | #include "operator_subscribe_test.hpp" 25 | 26 | namespace streamulus 27 | { 28 | int assert_eq::tests_passed = 0; 29 | 30 | void operator_subscribe_unit_tests::Run() 31 | { 32 | OpsBetweenTerminals(); 33 | OpsBetweenTerminalAndConst(); 34 | std::cout << "operator_subscribe_unit_tests completed. " << 35 | assert_eq::tests_passed << "/" << tests_run << " tests passed" << std::endl; 36 | 37 | Check(assert_eq::tests_passed == tests_run); 38 | } 39 | 40 | 41 | void operator_subscribe_unit_tests::OpsBetweenTerminals() 42 | { 43 | int v1_=7; 44 | int v2_=2; 45 | int v1=v1_; 46 | int v2=v2_; 47 | proto::terminal::type t1 = {v1}; 48 | proto::terminal::type t2 = {v2}; 49 | proto::terminal::type p1 = {&v1}; 50 | proto::terminal::type p2 = {&v2}; 51 | 52 | v1=v1_; v2=v2_; RunTest(-t1, -v1); 53 | v1=v1_; v2=v2_; RunTest(-t2, -v2); 54 | 55 | v1=v1_; v2=v2_; RunTest(*p1, v1); 56 | v1=v1_; v2=v2_; RunTest(*p2, v2); 57 | 58 | v1=v1_; v2=v2_; RunTest(~t1, ~v1); 59 | v1=v1_; v2=v2_; RunTest(~t2, ~v2); 60 | 61 | v1=v1_; v2=v2_; RunTest(!t1, !v1); 62 | v1=v1_; v2=v2_; RunTest(!t2, !v2); 63 | 64 | v1=v1_; v2=v2_; RunTest(++t1, ++v1); 65 | v1=v1_; v2=v2_; RunTest(++t2, ++v2); 66 | 67 | v1=v1_; v2=v2_; RunTest(--t1, --v1); 68 | v1=v1_; v2=v2_; RunTest(--t2, --v2); 69 | 70 | v1=v1_; v2=v2_; RunTest(t1++, v1++); 71 | v1=v1_; v2=v2_; RunTest(t2++, v2++); 72 | 73 | v1=v1_; v2=v2_; RunTest(t1--, v1--); 74 | v1=v1_; v2=v2_; RunTest(t2--, v2--); 75 | 76 | v1=v1_; v2=v2_; RunTest(t1 << t2, v1 << v2); 77 | v1=v1_; v2=v2_; RunTest(t2 << t1, v2 << v1); 78 | 79 | v1=v1_; v2=v2_; RunTest(t1 >> t2, v1 >> v2); 80 | v1=v1_; v2=v2_; RunTest(t2 >> t1, v2 >> v1); 81 | 82 | v1=v1_; v2=v2_; RunTest(t1 * t2, v1 * v2); 83 | v1=v1_; v2=v2_; RunTest(t2 * t1, v2 * v1); 84 | 85 | v1=v1_; v2=v2_; RunTest(t1 / t2, v1 / v2); 86 | v1=v1_; v2=v2_; RunTest(t2 / t1, v2 / v1); 87 | 88 | v1=v1_; v2=v2_; RunTest(t1 % t2, v1 % v2); 89 | v1=v1_; v2=v2_; RunTest(t2 % t1, v2 % v1); 90 | 91 | v1=v1_; v2=v2_; RunTest(t1 + t2, v1 + v2); 92 | v1=v1_; v2=v2_; RunTest(t2 + t1, v2 + v1); 93 | 94 | v1=v1_; v2=v2_; RunTest(t1 - t2, v1 - v2); 95 | v1=v1_; v2=v2_; RunTest(t2 - t1, v2 - v1); 96 | 97 | v1=v1_; v2=v2_; RunTest(t1 < t2, v1 < v2); 98 | v1=v1_; v2=v2_; RunTest(t2 < t1, v2 < v1); 99 | 100 | v1=v1_; v2=v2_; RunTest(t1 > t2, v1 > v2); 101 | v1=v1_; v2=v2_; RunTest(t2 > t1, v2 > v1); 102 | 103 | v1=v1_; v2=v2_; RunTest(t1 <= t2, v1 <= v2); 104 | v1=v1_; v2=v2_; RunTest(t2 <= t1, v2 <= v1); 105 | 106 | v1=v1_; v2=v2_; RunTest(t1 >= t2, v1 >= v2); 107 | v1=v1_; v2=v2_; RunTest(t2 >= t1, v2 >= v1); 108 | 109 | v1=v1_; v2=v2_; RunTest(t1 == t2, v1 == v2); 110 | v1=v1_; v2=v2_; RunTest(t2 == t1, v2 == v1); 111 | 112 | v1=v1_; v2=v2_; RunTest(t1 != t2, v1 != v2); 113 | v1=v1_; v2=v2_; RunTest(t2 != t1, v2 != v1); 114 | 115 | v1=v1_; v2=v2_; RunTest(t1 || t2, v1 || v2); 116 | v1=v1_; v2=v2_; RunTest(t2 || t1, v2 || v1); 117 | 118 | v1=v1_; v2=v2_; RunTest(t1 && t2, v1 && v2); 119 | v1=v1_; v2=v2_; RunTest(t2 && t1, v2 && v1); 120 | 121 | v1=v1_; v2=v2_; RunTest(t1 | t2, v1 | v2); 122 | v1=v1_; v2=v2_; RunTest(t2 | t1, v2 | v1); 123 | 124 | v1=v1_; v2=v2_; RunTest(t1 & t2, v1 & v2); 125 | v1=v1_; v2=v2_; RunTest(t2 & t1, v2 & v1); 126 | 127 | v1=v1_; v2=v2_; RunTest(t1 ^ t2, v1 ^ v2); 128 | v1=v1_; v2=v2_; RunTest(t2 ^ t1, v2 ^ v1); 129 | 130 | v1=v1_; v2=v2_; RunTest((t1 = t2), (v1 = v2)); 131 | v1=v1_; v2=v2_; RunTest((t2 = t1), (v2 = v1)); 132 | 133 | v1=v1_; v2=v2_; RunTest(t1 <<= t2, v1 <<= v2); 134 | v1=v1_; v2=v2_; RunTest(t2 <<= t1, v2 <<= v1); 135 | 136 | v1=v1_; v2=v2_; RunTest(t1 >>= t2, v1 >>= v2); 137 | v1=v1_; v2=v2_; RunTest(t2 >>= t1, v2 >>= v1); 138 | 139 | v1=v1_; v2=v2_; RunTest(t1 *= t2, v1 *= v2); 140 | v1=v1_; v2=v2_; RunTest(t2 *= t1, v2 *= v1); 141 | 142 | v1=v1_; v2=v2_; RunTest(t1 /= t2, v1 /= v2); 143 | v1=v1_; v2=v2_; RunTest(t2 /= t1, v2 /= v1); 144 | 145 | v1=v1_; v2=v2_; RunTest(t1 %= t2, v1 %= v2); 146 | v1=v1_; v2=v2_; RunTest(t2 %= t1, v2 %= v1); 147 | 148 | v1=v1_; v2=v2_; RunTest(t1 += t2, v1 += v2); 149 | v1=v1_; v2=v2_; RunTest(t2 += t1, v2 += v1); 150 | 151 | v1=v1_; v2=v2_; RunTest(t1 -= t2, v1 -= v2); 152 | v1=v1_; v2=v2_; RunTest(t2 -= t1, v2 -= v1); 153 | 154 | v1=v1_; v2=v2_; RunTest(t1 &= t2, v1 &= v2); 155 | v1=v1_; v2=v2_; RunTest(t2 &= t1, v2 &= v1); 156 | 157 | v1=v1_; v2=v2_; RunTest(t1 |= t2, v1 |= v2); 158 | v1=v1_; v2=v2_; RunTest(t2 |= t1, v2 |= v1); 159 | 160 | v1=v1_; v2=v2_; RunTest(t1 ^= t2, v1 ^= v2); 161 | v1=v1_; v2=v2_; RunTest(t2 ^= t1, v2 ^= v1); 162 | 163 | 164 | // TODO:: make these work 165 | v1=v1_; v2=v2_; RunTest(true ? t1 : t2, true ? v1 : v2); 166 | v1=v1_; v2=v2_; RunTest(true ? t2 : t1, true ? v2 : v1); 167 | 168 | v1=v1_; v2=v2_; RunTest(false ? t1 : t2, false ? v1 : v2); 169 | v1=v1_; v2=v2_; RunTest(false ? t2 : t1, false ? v2 : v1); 170 | 171 | } 172 | 173 | void operator_subscribe_unit_tests::OpsBetweenTerminalAndConst() 174 | { 175 | int v1_=7; 176 | int v1=v1_; 177 | proto::terminal::type t1 = {v1}; 178 | 179 | v1=v1_; RunTest(t1 << 2, v1 << 2); 180 | v1=v1_; RunTest(2 << t1, 2 << v1); 181 | 182 | v1=v1_; RunTest(t1 >> 2, v1 >> 2); 183 | v1=v1_; RunTest(2 >> t1, 2 >> v1); 184 | 185 | v1=v1_; RunTest(t1 * 2, v1 * 2); 186 | v1=v1_; RunTest(2 * t1, 2 * v1); 187 | 188 | v1=v1_; RunTest(t1 / 2, v1 / 2); 189 | v1=v1_; RunTest(2 / t1, 2 / v1); 190 | 191 | v1=v1_; RunTest(t1 % 2, v1 % 2); 192 | v1=v1_; RunTest(2 % t1, 2 % v1); 193 | 194 | v1=v1_; RunTest(t1 + 2, v1 + 2); 195 | v1=v1_; RunTest(2 + t1, 2 + v1); 196 | 197 | v1=v1_; RunTest(t1 - 2, v1 - 2); 198 | v1=v1_; RunTest(2 - t1, 2 - v1); 199 | 200 | v1=v1_; RunTest(t1 < 2, v1 < 2); 201 | v1=v1_; RunTest(2 < t1, 2 < v1); 202 | 203 | v1=v1_; RunTest(t1 > 2, v1 > 2); 204 | v1=v1_; RunTest(2 > t1, 2 > v1); 205 | 206 | v1=v1_; RunTest(t1 <= 2, v1 <= 2); 207 | v1=v1_; RunTest(2 <= t1, 2 <= v1); 208 | 209 | v1=v1_; RunTest(t1 >= 2, v1 >= 2); 210 | v1=v1_; RunTest(2 >= t1, 2 >= v1); 211 | 212 | v1=v1_; RunTest(t1 == 2, v1 == 2); 213 | v1=v1_; RunTest(2 == t1, 2 == v1); 214 | 215 | v1=v1_; RunTest(t1 != 2, v1 != 2); 216 | v1=v1_; RunTest(2 != t1, 2 != v1); 217 | 218 | v1=v1_; RunTest(t1 | 2, v1 | 2); 219 | v1=v1_; RunTest(2 | t1, 2 | v1); 220 | 221 | v1=v1_; RunTest(t1 & 2, v1 & 2); 222 | v1=v1_; RunTest(2 & t1, 2 & v1); 223 | 224 | v1=v1_; RunTest(t1 ^ 2, v1 ^ 2); 225 | v1=v1_; RunTest(2 ^ t1, 2 ^ v1); 226 | 227 | v1=v1_; RunTest((t1 = 2), (v1 = 2)); 228 | 229 | v1=v1_; RunTest(t1 <<= 2, v1 <<= 2); 230 | 231 | v1=v1_; RunTest(t1 >>= 2, v1 >>= 2); 232 | 233 | v1=v1_; RunTest(t1 *= 2, v1 *= 2); 234 | 235 | v1=v1_; RunTest(t1 /= 2, v1 /= 2); 236 | 237 | v1=v1_; RunTest(t1 %= 2, v1 %= 2); 238 | 239 | v1=v1_; RunTest(t1 += 2, v1 += 2); 240 | 241 | v1=v1_; RunTest(t1 -= 2, v1 -= 2); 242 | 243 | v1=v1_; RunTest(t1 &= 2, v1 &= 2); 244 | 245 | v1=v1_; RunTest(t1 |= 2, v1 |= 2); 246 | 247 | v1=v1_; RunTest(t1 ^= 2, v1 ^= 2); 248 | 249 | /* 250 | // TODO:: make these work 251 | v1=v1_; RunTest(proto::if_else, true ? v1 : 2); 252 | v1=v1_; RunTest(proto::if_else, true ? 2 : v1); 253 | 254 | v1=v1_; RunTest(proto::if_else, false ? v1 : 2); 255 | v1=v1_; RunTest(proto::if_else, false ? 2 : v1); 256 | */ 257 | } 258 | 259 | 260 | } // ns streamulus -------------------------------------------------------------------------------- /inst/tests/operator_functors_test.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // operator_functor_tests.cpp 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | 23 | #include "operator_functors_test.hpp" 24 | #include "operators.h" 25 | 26 | namespace streamulus 27 | { 28 | 29 | void operator_functors_unit_tests::Run() 30 | { 31 | namespace bp = boost::proto; 32 | 33 | int i0 = 7, j0 = 2; 34 | int i, j; 35 | int iexp, jexp; 36 | int *pi = &i; 37 | 38 | // Note: operators don't actually modify the stream, just generate a modified output. 39 | // So we compare the vale of the "stream" with unmodified input values 40 | 41 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i) == -iexp); Check(i==i0); Check(j==j0); 42 | i=iexp=i0; j=jexp=j0; Check(functor_of()(-i) == iexp); Check(i==i0); Check(j==j0); 43 | 44 | i=iexp=i0; j=jexp=j0; Check(functor_of()(pi) == iexp); Check(i==i0); Check(j==j0); 45 | 46 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i) == ~iexp); Check(i==i0); Check(j==j0); 47 | 48 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i) == !iexp); Check(i==i0); Check(j==j0); 49 | 50 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i) == ++iexp); Check(i==i0); Check(j==j0); 51 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i) == --iexp); Check(i==i0); Check(j==j0); 52 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i) == iexp++); Check(i==i0); Check(j==j0); 53 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i) == iexp--); Check(i==i0); Check(j==j0); 54 | 55 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp<()(j,i) == (jexp<()(i,j) == (iexp>>jexp)); Check(i==i0); Check(j==j0); 59 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp>>iexp)); Check(i==i0); Check(j==j0); 60 | 61 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp*jexp)); Check(i==i0); Check(j==j0); 62 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp*iexp)); Check(i==i0); Check(j==j0); 63 | 64 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp/jexp)); Check(i==i0); Check(j==j0); 65 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp/iexp)); Check(i==i0); Check(j==j0); 66 | 67 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp%jexp)); Check(i==i0); Check(j==j0); 68 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp%iexp)); Check(i==i0); Check(j==j0); 69 | 70 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp+jexp)); Check(i==i0); Check(j==j0); 71 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp+iexp)); Check(i==i0); Check(j==j0); 72 | 73 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp-jexp)); Check(i==i0); Check(j==j0); 74 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp-iexp)); Check(i==i0); Check(j==j0); 75 | 76 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp()(j,i) == (jexp()(i,j) == (iexp>jexp)); Check(i==i0); Check(j==j0); 80 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp>iexp)); Check(i==i0); Check(j==j0); 81 | 82 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp<=jexp)); Check(i==i0); Check(j==j0); 83 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp<=iexp)); Check(i==i0); Check(j==j0); 84 | 85 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp>=jexp)); Check(i==i0); Check(j==j0); 86 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp>=iexp)); Check(i==i0); Check(j==j0); 87 | 88 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp==jexp)); Check(i==i0); Check(j==j0); 89 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp==iexp)); Check(i==i0); Check(j==j0); 90 | 91 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp!=jexp)); Check(i==i0); Check(j==j0); 92 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp!=iexp)); Check(i==i0); Check(j==j0); 93 | 94 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp||jexp)); Check(i==i0); Check(j==j0); 95 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp||iexp)); Check(i==i0); Check(j==j0); 96 | 97 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp&&jexp)); Check(i==i0); Check(j==j0); 98 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp&&iexp)); Check(i==i0); Check(j==j0); 99 | 100 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp|jexp)); Check(i==i0); Check(j==j0); 101 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp|iexp)); Check(i==i0); Check(j==j0); 102 | 103 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp&jexp)); Check(i==i0); Check(j==j0); 104 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp&iexp)); Check(i==i0); Check(j==j0); 105 | 106 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp^jexp)); Check(i==i0); Check(j==j0); 107 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp^iexp)); Check(i==i0); Check(j==j0); 108 | 109 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp=jexp)); Check(i==i0); Check(j==j0); 110 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp=iexp)); Check(i==i0); Check(j==j0); 111 | 112 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp<<=jexp)); Check(i==i0); Check(j==j0); 113 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp<<=iexp)); Check(i==i0); Check(j==j0); 114 | 115 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp>>=jexp)); Check(i==i0); Check(j==j0); 116 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp>>=iexp)); Check(i==i0); Check(j==j0); 117 | 118 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp*=jexp)); Check(i==i0); Check(j==j0); 119 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp*=iexp)); Check(i==i0); Check(j==j0); 120 | 121 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp/=jexp)); Check(i==i0); Check(j==j0); 122 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp/=iexp)); Check(i==i0); Check(j==j0); 123 | 124 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp%=jexp)); Check(i==i0); Check(j==j0); 125 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp%=iexp)); Check(i==i0); Check(j==j0); 126 | 127 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp+=jexp)); Check(i==i0); Check(j==j0); 128 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp+=iexp)); Check(i==i0); Check(j==j0); 129 | 130 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp-=jexp)); Check(i==i0); Check(j==j0); 131 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp-=iexp)); Check(i==i0); Check(j==j0); 132 | 133 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp&=jexp)); Check(i==i0); Check(j==j0); 134 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp&=iexp)); Check(i==i0); Check(j==j0); 135 | 136 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp|=jexp)); Check(i==i0); Check(j==j0); 137 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp|=iexp)); Check(i==i0); Check(j==j0); 138 | 139 | i=iexp=i0; j=jexp=j0; Check(functor_of()(i,j) == (iexp^=jexp)); Check(i==i0); Check(j==j0); 140 | i=iexp=i0; j=jexp=j0; Check(functor_of()(j,i) == (jexp^=iexp)); Check(i==i0); Check(j==j0); 141 | 142 | // subscript_func 143 | 144 | i=iexp=i0; j=jexp=j0; Check(functor_of()(true,i,j) == (true ? iexp : jexp)); Check(i==i0); Check(j==j0); 145 | i=iexp=i0; j=jexp=j0; Check(functor_of()(true,j,i) == (true ? jexp : iexp)); Check(i==i0); Check(j==j0); 146 | i=iexp=i0; j=jexp=j0; Check(functor_of()(false,i,j) == (false ? iexp : jexp)); Check(i==i0); Check(j==j0); 147 | i=iexp=i0; j=jexp=j0; Check(functor_of()(false,j,i) == (false ? jexp : iexp)); Check(i==i0); Check(j==j0); 148 | 149 | std::cout << "operator_functors_unit_tests completed." << std::endl; 150 | } 151 | 152 | 153 | } // ns streamulus 154 | -------------------------------------------------------------------------------- /inst/include/grammar.h: -------------------------------------------------------------------------------- 1 | // 2 | // grammar.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | #include "transforms.h" 25 | #include "operators.h" 26 | 27 | #include "composed_func.h" 28 | 29 | #include 30 | 31 | namespace streamulus 32 | { 33 | struct smls_grammar; 34 | 35 | // ************************************* HELPER ************************************* 36 | struct get_terminal_value 37 | : proto::when, proto::_value> 38 | { 39 | }; 40 | 41 | 42 | // ******************************* OPERATOR CATEGORIES ****************************** 43 | 44 | struct UnaryOpCases 45 | { 46 | // The primary template matches nothing: 47 | template 48 | struct case_ 49 | : proto::not_ 50 | {}; 51 | }; 52 | 53 | template<> struct UnaryOpCases::case_ : proto::unary_plus {}; 54 | template<> struct UnaryOpCases::case_ : proto::negate {}; 55 | template<> struct UnaryOpCases::case_ : proto::dereference {}; 56 | template<> struct UnaryOpCases::case_ : proto::complement {}; 57 | template<> struct UnaryOpCases::case_ : proto::logical_not {}; 58 | template<> struct UnaryOpCases::case_ : proto::pre_inc {}; 59 | template<> struct UnaryOpCases::case_ : proto::pre_dec {}; 60 | template<> struct UnaryOpCases::case_ : proto::post_inc {}; 61 | template<> struct UnaryOpCases::case_ : proto::post_dec {}; 62 | 63 | struct BinaryOpCases 64 | { 65 | // The primary template matches nothing: 66 | template 67 | struct case_ 68 | : proto::not_ 69 | {}; 70 | }; 71 | 72 | template<> struct BinaryOpCases::case_ : proto::shift_left {}; 73 | template<> struct BinaryOpCases::case_ : proto::shift_right {}; 74 | template<> struct BinaryOpCases::case_ : proto::multiplies {}; 75 | template<> struct BinaryOpCases::case_ : proto::divides {}; 76 | template<> struct BinaryOpCases::case_ : proto::modulus {}; 77 | template<> struct BinaryOpCases::case_ : proto::plus {}; 78 | template<> struct BinaryOpCases::case_ : proto::minus {}; 79 | template<> struct BinaryOpCases::case_ : proto::less {}; 80 | template<> struct BinaryOpCases::case_ : proto::greater {}; 81 | template<> struct BinaryOpCases::case_ : proto::less_equal {}; 82 | template<> struct BinaryOpCases::case_ : proto::greater_equal {}; 83 | template<> struct BinaryOpCases::case_ : proto::equal_to {}; 84 | template<> struct BinaryOpCases::case_ : proto::not_equal_to {}; 85 | template<> struct BinaryOpCases::case_ : proto::logical_or {}; 86 | template<> struct BinaryOpCases::case_ : proto::logical_and {}; 87 | template<> struct BinaryOpCases::case_ : proto::bitwise_or {}; 88 | template<> struct BinaryOpCases::case_ : proto::bitwise_and {}; 89 | template<> struct BinaryOpCases::case_ : proto::bitwise_xor {}; 90 | template<> struct BinaryOpCases::case_ : proto::subscript {}; 91 | template<> struct BinaryOpCases::case_ : proto::assign {}; 92 | template<> struct BinaryOpCases::case_ : proto::shift_left_assign {}; 93 | template<> struct BinaryOpCases::case_ : proto::shift_right_assign {}; 94 | template<> struct BinaryOpCases::case_ : proto::multiplies_assign {}; 95 | template<> struct BinaryOpCases::case_ : proto::divides_assign {}; 96 | template<> struct BinaryOpCases::case_ : proto::modulus_assign {}; 97 | template<> struct BinaryOpCases::case_ : proto::plus_assign {}; 98 | template<> struct BinaryOpCases::case_ : proto::minus_assign {}; 99 | template<> struct BinaryOpCases::case_ : proto::bitwise_and_assign {}; 100 | template<> struct BinaryOpCases::case_ : proto::bitwise_or_assign {}; 101 | template<> struct BinaryOpCases::case_ : proto::bitwise_xor_assign {}; 102 | 103 | struct UnsupportedOpCases 104 | { 105 | // The primary template matches nothing: 106 | template 107 | struct case_ 108 | : proto::not_ 109 | {}; 110 | }; 111 | 112 | // Disabling the address-of operator. It is a special case in proto and is problematic to 113 | // support. It is also a bit nonsensical for streams. 114 | template<> struct UnsupportedOpCases::case_ : proto::address_of {}; 115 | template<> struct UnsupportedOpCases::case_ : proto::comma {}; 116 | 117 | // ********************************* SLIDING WINDOWS ********************************* 118 | 119 | struct window_ {}; 120 | 121 | 122 | // ************************************** RULES ************************************** 123 | 124 | // terminals 125 | struct strop_terminal_rule : proto::terminal > {}; 126 | struct const_terminal_rule : proto::terminal {}; 127 | 128 | 129 | struct unary_op_rule : proto::switch_ {}; 130 | struct binary_op_rule : proto::switch_ {}; 131 | struct ternary_op_rule : proto::if_else_ {}; 132 | struct unsupported_op_rule : proto::switch_ {}; 133 | 134 | struct window_rule : proto::function, proto::terminal, smls_grammar> {}; 135 | 136 | struct func_terminal : proto::and_,proto::not_ > > {}; 137 | struct function_0_rule : proto::function {}; 138 | struct function_1_rule : proto::function {}; 139 | struct function_2_rule : proto::function {}; 140 | struct function_3_rule : proto::function {}; 141 | struct function_4_rule : proto::function {}; 142 | struct function_5_rule : proto::function {}; 143 | 144 | 145 | // ************************************** GRAMMAR ************************************** 146 | 147 | struct smls_grammar; 148 | 149 | struct smls_grammar_cases 150 | { 151 | 152 | // The primary template matches nothing: 153 | template 154 | struct case_ 155 | : proto::or_< 156 | proto::when(), smls_grammar(proto::_child), proto::_state)> 158 | 159 | , proto::when(), smls_grammar(proto::_left), 161 | smls_grammar(proto::_right), proto::_state)> 162 | , proto::when(), smls_grammar(proto::_child0), 164 | smls_grammar(proto::_child1), 165 | smls_grammar(proto::_child2), proto::_state)> 166 | > 167 | {}; 168 | }; 169 | 170 | // Terminal expressions 171 | template<> 172 | struct smls_grammar_cases::case_ 173 | : proto::when 174 | {}; 175 | 176 | 177 | // ////////////////////////////// Function expressions ////////////////////////////// 178 | 179 | 180 | template<> 181 | struct smls_grammar_cases::case_ 182 | : proto::or_< 183 | proto::when 186 | , proto::when 189 | , proto::when 194 | , proto::when 200 | , proto::when 207 | , proto::when 215 | , proto::when 224 | > 225 | {}; 226 | 227 | 228 | // The grammar 229 | struct smls_grammar 230 | : proto::switch_ 231 | {}; 232 | 233 | 234 | } // ns streamulus 235 | -------------------------------------------------------------------------------- /inst/include/engine.h: -------------------------------------------------------------------------------- 1 | // 2 | // engine.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | #include "graph.h" 25 | #include "strop_base.h" 26 | #include "grammar.h" 27 | #include "subscription.h" 28 | #include "stream.h" 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | 36 | namespace streamulus 37 | { 38 | 39 | class Engine : public boost::noncopyable 40 | { 41 | public: 42 | 43 | Engine() 44 | : mWorking(false) 45 | , mCurrentTime(0) 46 | , mVerbose(false) 47 | , mNumRemovedVertices(0) 48 | { 49 | }; 50 | 51 | 52 | void AddVertexToGraph(const StropPtr& strop) 53 | { 54 | boost::add_vertex(strop, mGraph); 55 | GraphChanged(); 56 | } 57 | 58 | void AddSource(const StropPtr& strop) 59 | { 60 | mSources.push_back(strop); 61 | } 62 | 63 | template 64 | void AddEdgeToGraph(const StropPtr& source, 65 | const StropPtr& target, 66 | const StreamPtrType& stream) 67 | { 68 | StreamPtr stream_ptr(stream); 69 | //Graph::edge_descriptor desc = boost::add_edge(source->GetDescriptor(), target->GetDescriptor(), stream_ptr, mGraph).first; 70 | if (stream->IsValid()) 71 | mSources.push_back(target); 72 | GraphChanged(); 73 | } 74 | 75 | 76 | template 77 | void Output(const BoostGraph::vertex_descriptor& source, const T& value) 78 | { 79 | BoostGraph::out_edge_iterator it, it_end; 80 | 81 | for (boost::tie(it,it_end) = boost::out_edges(source, mGraph); it != it_end; ++it) 82 | { 83 | BoostGraph::edge_descriptor edge(*it); 84 | 85 | // Put the data on the edge's stream 86 | StreamPtr stream(mGraph[edge]); 87 | static_cast*>(stream.get())->Append(value); 88 | 89 | ActivateVertex(boost::target(edge, mGraph)); 90 | } 91 | Work(); 92 | } 93 | 94 | 95 | void Work() 96 | { 97 | if (mWorking) 98 | return; 99 | mWorking = true; 100 | 101 | 102 | StreamulusOut << "Work called. mQueue.size() = " << mQueue.size() << std::endl; 103 | while (!mQueue.empty()) 104 | { 105 | std::set::iterator it = mQueue.begin(); 106 | mCurrentTime = std::max(mCurrentTime,it->mTime); 107 | 108 | StropPtr& strop(it->mStrop); 109 | strop->Work(); 110 | strop->SetIsActive(false); 111 | mQueue.erase(it); 112 | } 113 | mWorking = false; 114 | } 115 | 116 | inline bool IsVerbose() 117 | { 118 | return mVerbose; 119 | } 120 | 121 | template 122 | struct ExpressionResultType 123 | { 124 | // Get the type of the strop created by the expression 125 | typedef typename boost::result_of::type result_strop_type; 126 | // Extract the output type 127 | typedef typename StropReturnType::type type; 128 | }; 129 | 130 | template 131 | const typename Subscription::type>::type 132 | Subscribe(const Expr &expr) 133 | { 134 | typedef typename ExpressionResultType::type R; 135 | 136 | // if (IsVerbose()) 137 | // boost::proto::display_expr(expr, StreamulusOut); // pass io object on 138 | 139 | // Make sure the expression conforms to our grammar 140 | BOOST_MPL_ASSERT(( boost::proto::matches )); 141 | 142 | // add the expression to the graph 143 | typedef typename Subscription::strop_type ResultStropType; 144 | ResultStropType result = smls_grammar()(expr, this); 145 | 146 | result->AddExternalReference(); 147 | 148 | StartEngine(); 149 | 150 | // typedef const boost::shared_ptr > strop_type; 151 | // const streamulus_expr::type> 152 | 153 | typename Subscription::terminal_type terminal = {result}; 154 | return terminal; 155 | } 156 | 157 | template 158 | void UnSubscribe(const typename Subscription::type& subscription) 159 | { 160 | typedef typename Subscription::strop_type StropType; 161 | const StropType& strop(boost::proto::value(subscription)); 162 | strop->RemoveExternalReference(); 163 | RemoveVertexFromGraph(strop); 164 | GarbageCollect(); 165 | } 166 | 167 | private: 168 | 169 | void StartEngine() 170 | { 171 | #if defined(WRITE_GRAPH) 172 | WriteGraph("TsGraph.vis"); 173 | #endif 174 | ActivateSources(); 175 | Work(); 176 | } 177 | 178 | void ActivateVertex(const BoostGraph::vertex_descriptor& vertex) 179 | { 180 | ActivateVertex(mGraph[vertex]); 181 | } 182 | 183 | void ActivateVertex(StropPtr& strop) 184 | { 185 | assert(strop->GetEngine()); 186 | 187 | if (strop->IsActive() || strop->IsDeleted()) 188 | return; 189 | 190 | mQueue.insert(QueueEntry(mCurrentTime++, strop->GetTopSortIndex(), strop)); 191 | strop->SetIsActive(true); 192 | } 193 | 194 | void ActivateSources() 195 | { 196 | if (IsVerbose()) 197 | StreamulusOut << "Activate sources: mSources.size() = " << mSources.size() << std::endl; 198 | for (std::vector::iterator it = mSources.begin(); it != mSources.end(); ++it) 199 | ActivateVertex(*it); 200 | mSources.clear(); 201 | } 202 | 203 | bool IsRemoveable(const StropPtr& strop) 204 | { 205 | // A node is removeable if it does not have an external reference or an 206 | // unremoved successor 207 | 208 | if (strop->HasExternalReference()) 209 | return false; 210 | 211 | BoostGraph::out_edge_iterator it, it_end; 212 | 213 | for (boost::tie(it,it_end) = boost::out_edges(strop->GetDescriptor(), mGraph); it != it_end; ++it) 214 | { 215 | BoostGraph::edge_descriptor edge(*it); 216 | if (! mGraph[boost::target(edge, mGraph)]->IsDeleted()) 217 | return false; 218 | } 219 | 220 | return true; 221 | } 222 | 223 | void RemoveVertexFromGraph(const StropPtr& strop) 224 | { 225 | if (!IsRemoveable(strop)) 226 | return; 227 | 228 | strop->MarkAsDeleted(); 229 | mNumRemovedVertices++; 230 | BoostGraph::in_edge_iterator it, it_end; 231 | 232 | for (boost::tie(it,it_end) = boost::in_edges(strop->GetDescriptor(), mGraph); it != it_end; ++it) 233 | { 234 | BoostGraph::edge_descriptor edge(*it); 235 | const StropPtr& pred(mGraph[boost::source(edge, mGraph)]); 236 | RemoveVertexFromGraph(pred); 237 | } 238 | } 239 | 240 | void GarbageCollect() 241 | { 242 | if ( 2*mNumRemovedVertices < boost::num_vertices(mGraph) ) 243 | return; 244 | 245 | DoGarbageCollection(); 246 | mNumRemovedVertices=0; 247 | } 248 | 249 | void DoGarbageCollection() 250 | { 251 | Graph new_graph; 252 | 253 | std::map descriptors_old2new; 254 | 255 | // copy live nodes 256 | BoostGraph::vertex_iterator vit, vit_end; 257 | for (boost::tie(vit,vit_end) = boost::vertices(mGraph); vit != vit_end; ++vit) 258 | { 259 | const StropPtr& strop(mGraph[*vit]); 260 | if (! strop->IsDeleted()) 261 | descriptors_old2new[strop->GetDescriptor()] = boost::add_vertex(strop, new_graph); 262 | } 263 | 264 | // copy live edges 265 | BoostGraph::edge_iterator eit, eit_end; 266 | for (boost::tie(eit,eit_end) = boost::edges(mGraph); eit != eit_end; ++eit) 267 | { 268 | BoostGraph::edge_descriptor edge(*eit); 269 | const StropPtr& source(mGraph[boost::source(edge, mGraph)]); 270 | const StropPtr& target(mGraph[boost::target(edge, mGraph)]); 271 | 272 | if (! (source->IsDeleted() || target->IsDeleted())) 273 | { 274 | boost::add_edge(descriptors_old2new[source->GetDescriptor()], 275 | descriptors_old2new[target->GetDescriptor()], 276 | mGraph[*eit], 277 | new_graph); 278 | } 279 | } 280 | 281 | mGraph.swap(new_graph); 282 | GraphChanged(); 283 | } 284 | 285 | struct TopologicalSortVisitor : public boost::default_dfs_visitor 286 | { // Reset descriptors and recompute topological order labels in the graph: 287 | public: 288 | TopologicalSortVisitor(Graph & g, Engine* engine) 289 | : mIndex(boost::num_vertices(g)) 290 | , mGraph(g) 291 | , mEngine(engine) 292 | { 293 | } 294 | 295 | void finish_vertex(BoostGraph::vertex_descriptor u, const BoostGraph & g) 296 | { 297 | assert( mIndex > 0); 298 | mGraph[u]->SetGraph(mEngine, u, mIndex--); 299 | 300 | if (mEngine->IsVerbose()) 301 | { 302 | StreamulusOut << "Finish vertex " << u << " " // << mGraph[u]->GetName() 303 | << " TO=" << mGraph[u]->GetTopSortIndex() << std::endl; 304 | } 305 | } 306 | private: 307 | size_t mIndex; 308 | Graph& mGraph; 309 | Engine* mEngine; 310 | }; 311 | 312 | void GraphChanged() 313 | { 314 | TopologicalSortVisitor vis(mGraph, this); 315 | boost::depth_first_search(mGraph, boost::visitor(vis)); 316 | } 317 | 318 | 319 | typedef long TimestampT; 320 | 321 | struct QueueEntry 322 | { 323 | QueueEntry(TimestampT time, 324 | size_t top_sort_index, 325 | StropPtr& strop) 326 | : mTime(time) 327 | , mTopSortIndex(top_sort_index) 328 | , mStrop(strop) 329 | { 330 | } 331 | 332 | bool operator<(const QueueEntry& rhs ) const 333 | { 334 | // sort by (time, topological order) 335 | return (this->mTimemTime==rhs.mTime && this->mTopSortIndexGetDescriptor() 354 | << "_TO" << mGraph[v]->GetTopSortIndex() << "]"; 355 | } 356 | 357 | private: 358 | Graph& mGraph; 359 | }; 360 | 361 | void WriteGraph(const std::string& filename) 362 | { 363 | if (IsVerbose()) 364 | StreamulusOut << "Writing graph to " << filename << std::endl; 365 | std::ofstream file; 366 | file.open (filename.c_str()); 367 | boost::write_graphviz(file, mGraph, VertexPropertyWriter(mGraph)); 368 | file.close(); 369 | } 370 | 371 | Graph mGraph; 372 | std::set mQueue; 373 | bool mWorking; 374 | TimestampT mCurrentTime; 375 | std::vector mSources; 376 | bool mVerbose; 377 | unsigned int mNumRemovedVertices; 378 | 379 | }; 380 | 381 | 382 | } // ns streamulus 383 | -------------------------------------------------------------------------------- /inst/include/transforms.h: -------------------------------------------------------------------------------- 1 | // 2 | // transforms.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | // Transforms for streamulus grammar 25 | 26 | #include "stream.h" 27 | #include "strop.h" 28 | #include "strop_func.h" 29 | #include "strop_sliding_window.h" 30 | #include "input_stream.h" 31 | #include "strop_return_type.h" 32 | #include "funcs.h" 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | 41 | namespace streamulus 42 | { 43 | 44 | using namespace boost; 45 | 46 | //////////////////////////// Utilities //////////////////////////// 47 | template 48 | struct BaseType 49 | { 50 | static const bool value = false; 51 | }; 52 | 53 | template 54 | struct BaseType > 55 | { 56 | static const bool value = true; 57 | typedef Type type; 58 | }; 59 | 60 | template 61 | struct MakeStropPtrType 62 | { 63 | typedef boost::shared_ptr > type; 64 | }; 65 | 66 | //////////////////////////// Transforms //////////////////////////// 67 | 68 | struct AddStropToGraph : proto::callable 69 | { 70 | template struct result; 71 | 72 | template 73 | struct result 74 | { 75 | typedef typename boost::remove_reference::type type; 76 | }; 77 | 78 | template 79 | const StropType operator()(StropType strop, State engine) 80 | { 81 | if (!strop->GetEngine()) 82 | { 83 | engine->AddVertexToGraph(strop); 84 | engine->AddSource(strop); 85 | } 86 | if (engine->IsVerbose()) 87 | StreamulusOut << "AddStropToGraph: " << strop << " returning " << strop->GetDescriptor() << std::endl; 88 | return strop; 89 | } 90 | }; 91 | 92 | 93 | struct generic_func : proto::callable 94 | { 95 | template struct result; 96 | 97 | // Arity = 0 98 | template 99 | struct result 100 | { 101 | typedef typename boost::remove_const::type>::type F; 102 | typedef typename F::template result::type R; 103 | typedef const boost::shared_ptr > type; 104 | }; 105 | 106 | template 107 | typename result::type 108 | operator()(const F& f, State engine) 109 | { 110 | if (engine->IsVerbose()) 111 | StreamulusOut << "generic_func" << std::endl; 112 | //typedef result Result; 113 | typedef Func0 FuncStropType; 114 | 115 | boost::shared_ptr funcStropPtr(new FuncStropType(f)); 116 | engine->AddVertexToGraph(funcStropPtr); 117 | engine->AddSource(funcStropPtr); 118 | return funcStropPtr; 119 | } 120 | 121 | // Arity = 1 122 | template 125 | struct result 126 | { 127 | typedef typename boost::remove_const::type>::type F; 128 | typedef typename StropReturnType::type Arg1Type; 129 | typedef typename F::template result::type R; 130 | typedef const boost::shared_ptr > type; 131 | }; 132 | 133 | template 136 | typename result::type 137 | operator()(const F& f, 138 | const Arg1Strop arg1, 139 | State engine) 140 | { 141 | if (engine->IsVerbose()) 142 | StreamulusOut << "generic_func" << std::endl; 143 | typedef result Result; 144 | typedef Func1 FuncStropType; 147 | 148 | boost::shared_ptr funcStropPtr(new FuncStropType(f)); 149 | 150 | typename BaseType::type::OutputStreamPtr arg1Stream(arg1->MakeOutputStream()); 151 | funcStropPtr->SetInputs(boost::fusion::make_vector(arg1Stream)); 152 | 153 | engine->AddVertexToGraph(funcStropPtr); 154 | engine->AddEdgeToGraph(arg1, funcStropPtr, arg1Stream); 155 | return funcStropPtr; 156 | } 157 | 158 | // Arity = 2 159 | template 160 | struct result 161 | { 162 | typedef typename boost::remove_const::type>::type F; 163 | typedef typename StropReturnType::type Arg1Type; 164 | typedef typename StropReturnType::type Arg2Type; 165 | typedef typename F::template result::type R; 166 | typedef const boost::shared_ptr > type; 167 | }; 168 | 169 | template 170 | typename result::type 171 | operator()(const F& f,const Arg1Strop arg1, const Arg2Strop arg2, State engine) 172 | { 173 | if (engine->IsVerbose()) 174 | StreamulusOut << "generic_func" << std::endl; 175 | typedef result Result; 176 | typedef Func2 FuncStropType; 177 | boost::shared_ptr funcStropPtr(new FuncStropType(f)); 178 | 179 | typename BaseType::type::OutputStreamPtr arg1Stream(arg1->MakeOutputStream()); 180 | typename BaseType::type::OutputStreamPtr arg2Stream(arg2->MakeOutputStream()); 181 | funcStropPtr->SetInputs(boost::fusion::make_vector(arg1Stream, arg2Stream)); 182 | 183 | engine->AddVertexToGraph(funcStropPtr); 184 | engine->AddEdgeToGraph(arg1, funcStropPtr, arg1Stream); 185 | engine->AddEdgeToGraph(arg2, funcStropPtr, arg2Stream); 186 | return funcStropPtr; 187 | } 188 | 189 | // Arity = 3 190 | template 195 | struct result 196 | { 197 | typedef typename boost::remove_const::type>::type F; 198 | typedef typename StropReturnType::type Arg1Type; 199 | typedef typename StropReturnType::type Arg2Type; 200 | typedef typename StropReturnType::type Arg3Type; 201 | typedef typename F::template result::type R; 202 | typedef const boost::shared_ptr > type; 203 | }; 204 | 205 | template 210 | typename result::type 211 | operator()(const F& f, 212 | const Arg1Strop arg1, 213 | const Arg2Strop arg2, 214 | const Arg3Strop arg3, 215 | State engine) 216 | { 217 | if (engine->IsVerbose()) 218 | StreamulusOut << "generic_func" << std::endl; 219 | typedef result Result; 220 | typedef Func3 FuncStropType; 225 | 226 | boost::shared_ptr funcStropPtr(new FuncStropType(f)); 227 | 228 | typename BaseType::type::OutputStreamPtr arg1Stream(arg1->MakeOutputStream()); 229 | typename BaseType::type::OutputStreamPtr arg2Stream(arg2->MakeOutputStream()); 230 | typename BaseType::type::OutputStreamPtr arg3Stream(arg3->MakeOutputStream()); 231 | funcStropPtr->SetInputs(boost::fusion::make_vector(arg1Stream, arg2Stream, arg3Stream)); 232 | 233 | engine->AddVertexToGraph(funcStropPtr); 234 | engine->AddEdgeToGraph(arg1, funcStropPtr, arg1Stream); 235 | engine->AddEdgeToGraph(arg2, funcStropPtr, arg2Stream); 236 | engine->AddEdgeToGraph(arg3, funcStropPtr, arg3Stream); 237 | return funcStropPtr; 238 | } 239 | 240 | // Arity = 4 241 | template 247 | struct result 248 | { 249 | typedef typename boost::remove_const::type>::type F; 250 | typedef typename StropReturnType::type Arg1Type; 251 | typedef typename StropReturnType::type Arg2Type; 252 | typedef typename StropReturnType::type Arg3Type; 253 | typedef typename StropReturnType::type Arg4Type; 254 | typedef typename F::template result::type R; 255 | typedef const boost::shared_ptr > type; 256 | }; 257 | 258 | template 264 | typename result::type 265 | operator()(const F& f, 266 | const Arg1Strop arg1, 267 | const Arg2Strop arg2, 268 | const Arg3Strop arg3, 269 | const Arg4Strop arg4, 270 | State engine) 271 | { 272 | if (engine->IsVerbose()) 273 | StreamulusOut << "generic_func" << std::endl; 274 | typedef result Result; 275 | typedef Func4 FuncStropType; 281 | 282 | boost::shared_ptr funcStropPtr(new FuncStropType(f)); 283 | 284 | typename BaseType::type::OutputStreamPtr arg1Stream(arg1->MakeOutputStream()); 285 | typename BaseType::type::OutputStreamPtr arg2Stream(arg2->MakeOutputStream()); 286 | typename BaseType::type::OutputStreamPtr arg3Stream(arg3->MakeOutputStream()); 287 | typename BaseType::type::OutputStreamPtr arg4Stream(arg4->MakeOutputStream()); 288 | funcStropPtr->SetInputs(boost::fusion::make_vector(arg1Stream, arg2Stream, arg3Stream, arg4Stream)); 289 | 290 | engine->AddVertexToGraph(funcStropPtr); 291 | engine->AddEdgeToGraph(arg1, funcStropPtr, arg1Stream); 292 | engine->AddEdgeToGraph(arg2, funcStropPtr, arg2Stream); 293 | engine->AddEdgeToGraph(arg3, funcStropPtr, arg3Stream); 294 | engine->AddEdgeToGraph(arg4, funcStropPtr, arg4Stream); 295 | return funcStropPtr; 296 | } 297 | 298 | // Arity = 5 299 | template 306 | struct result 307 | { 308 | typedef typename boost::remove_const::type>::type F; 309 | typedef typename StropReturnType::type Arg1Type; 310 | typedef typename StropReturnType::type Arg2Type; 311 | typedef typename StropReturnType::type Arg3Type; 312 | typedef typename StropReturnType::type Arg4Type; 313 | typedef typename StropReturnType::type Arg5Type; 314 | typedef typename F::template result::type R; 315 | typedef const boost::shared_ptr > type; 316 | }; 317 | 318 | template 325 | typename result::type 326 | operator()(const F& f, 327 | const Arg1Strop arg1, 328 | const Arg2Strop arg2, 329 | const Arg3Strop arg3, 330 | const Arg4Strop arg4, 331 | const Arg5Strop arg5, 332 | State engine) 333 | { 334 | if (engine->IsVerbose()) 335 | StreamulusOut << "generic_func" << std::endl; 336 | typedef result Result; 337 | typedef Func5 FuncStropType; 344 | 345 | boost::shared_ptr funcStropPtr(new FuncStropType(f)); 346 | 347 | typename BaseType::type::OutputStreamPtr arg1Stream(arg1->MakeOutputStream()); 348 | typename BaseType::type::OutputStreamPtr arg2Stream(arg2->MakeOutputStream()); 349 | typename BaseType::type::OutputStreamPtr arg3Stream(arg3->MakeOutputStream()); 350 | typename BaseType::type::OutputStreamPtr arg4Stream(arg4->MakeOutputStream()); 351 | typename BaseType::type::OutputStreamPtr arg5Stream(arg5->MakeOutputStream()); 352 | funcStropPtr->SetInputs(boost::fusion::make_vector(arg1Stream, arg2Stream, arg3Stream, arg4Stream, arg5Stream)); 353 | 354 | engine->AddVertexToGraph(funcStropPtr); 355 | engine->AddEdgeToGraph(arg1, funcStropPtr, arg1Stream); 356 | engine->AddEdgeToGraph(arg2, funcStropPtr, arg2Stream); 357 | engine->AddEdgeToGraph(arg3, funcStropPtr, arg3Stream); 358 | engine->AddEdgeToGraph(arg4, funcStropPtr, arg4Stream); 359 | engine->AddEdgeToGraph(arg5, funcStropPtr, arg5Stream); 360 | return funcStropPtr; 361 | } 362 | 363 | }; 364 | 365 | 366 | struct HandleTerminal : proto::callable 367 | { 368 | template struct result; 369 | 370 | // Case 1: terminal is a shared_ptr to a strop 371 | template 372 | struct result&,State)> 373 | { 374 | typedef const boost::shared_ptr& StropPtrType; 375 | typedef typename AddStropToGraph::result::type type; 376 | }; 377 | 378 | template 379 | struct result,State)> 380 | : result&,State)> 381 | {}; 382 | 383 | template 384 | typename boost::enable_if, typename result::type>::type 385 | operator()(StropType strop, State engine) 386 | { 387 | return AddStropToGraph()(strop, engine); 388 | } 389 | 390 | // Final case: Terminal is any other constant 391 | template 392 | struct result 393 | { 394 | typedef typename ConstFunc::template result(ConstType)>::type ConstFuncResultType; 395 | typedef const boost::shared_ptr > type; 396 | }; 397 | 398 | template 399 | typename boost::disable_if, typename result::type>::type 400 | operator()(ConstType const_value, State engine) 401 | { 402 | typedef typename result::ConstFuncResultType T; 403 | return generic_func()(ConstFunc(const_value),engine); 404 | } 405 | 406 | }; 407 | 408 | 409 | struct SlidingWindow : proto::callable 410 | { 411 | template struct result; 412 | 413 | template 414 | struct result 415 | { 416 | typedef typename StropReturnType::type input_type; 417 | typedef typename WindowUpdateType::type result_type; 418 | typedef const boost::shared_ptr > type; 419 | }; 420 | 421 | template 422 | typename result::type 423 | operator()(const int& size, const ArgStrop arg, State engine) 424 | { 425 | typedef Window::type> WindowStropType; 426 | boost::shared_ptr strop(new WindowStropType(size)); 427 | 428 | typename BaseType::type::OutputStreamPtr argStream(arg->MakeOutputStream()); 429 | strop->SetInputs(boost::fusion::make_vector(argStream)); 430 | 431 | engine->AddVertexToGraph(strop); 432 | engine->AddEdgeToGraph(arg, strop, argStream); 433 | return strop; 434 | } 435 | }; 436 | 437 | 438 | 439 | 440 | } // ns streamulus 441 | -------------------------------------------------------------------------------- /inst/include/operators.h: -------------------------------------------------------------------------------- 1 | // 2 | // operators.h 3 | // 4 | // Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved. 5 | // 6 | // This file is part of Streamulus. 7 | // 8 | // Streamulus is free software: you can redistribute it and/or modify 9 | // it under the terms of the GNU General Public License as published by 10 | // the Free Software Foundation, either version 3 of the License, or 11 | // (at your option) any later version. 12 | // 13 | // Streamulus is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | // GNU General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU General Public License 19 | // along with Streamulus. If not, see . 20 | // 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | 27 | namespace streamulus 28 | { 29 | template 30 | struct functor_of; 31 | 32 | template<> 33 | struct functor_of 34 | { 35 | template struct result; 36 | 37 | template 38 | struct result 39 | { 40 | typedef A type; 41 | }; 42 | 43 | template 44 | typename result(A)>::type 45 | operator()(const A& value) const 46 | { 47 | return +value; 48 | } 49 | }; 50 | 51 | template<> 52 | struct functor_of 53 | { 54 | template struct result; 55 | 56 | template 57 | struct result 58 | { 59 | typedef A type; 60 | }; 61 | 62 | template 63 | typename result(A)>::type 64 | operator()(const A& value) const 65 | { 66 | return -value; 67 | } 68 | }; 69 | 70 | template<> 71 | struct functor_of 72 | { 73 | template struct result; 74 | 75 | template 76 | struct result 77 | { 78 | typedef typename boost::remove_pointer::type type; 79 | }; 80 | 81 | template 82 | typename result (A)>::type 83 | operator()(const A& value) const 84 | { 85 | return *value; 86 | } 87 | }; 88 | 89 | 90 | template<> 91 | struct functor_of 92 | { 93 | template struct result; 94 | 95 | template 96 | struct result 97 | { 98 | typedef A type; 99 | }; 100 | 101 | template 102 | typename result(A)>::type 103 | operator()(const A& value) const 104 | { 105 | return ~value; 106 | } 107 | }; 108 | 109 | template<> 110 | struct functor_of 111 | { 112 | template struct result; 113 | 114 | template 115 | struct result 116 | { 117 | typedef typename boost::add_pointer::type type; 118 | }; 119 | 120 | template 121 | typename result(A)>::type 122 | operator()(A& value) const 123 | { 124 | return &value; 125 | } 126 | }; 127 | 128 | template<> 129 | struct functor_of 130 | { 131 | template struct result; 132 | 133 | template 134 | struct result 135 | { 136 | typedef bool type; 137 | }; 138 | 139 | template 140 | typename result(A)>::type 141 | operator()(const A& value) const 142 | { 143 | return !value; 144 | } 145 | }; 146 | 147 | template<> 148 | struct functor_of 149 | { 150 | template struct result; 151 | 152 | template 153 | struct result 154 | { 155 | typedef A type; 156 | }; 157 | 158 | template 159 | typename result(A)>::type 160 | operator()(A& value) const 161 | { 162 | typename boost::remove_const::type res(value); 163 | return ++res; 164 | } 165 | }; 166 | 167 | template<> 168 | struct functor_of 169 | { 170 | template struct result; 171 | 172 | template 173 | struct result 174 | { 175 | typedef A type; 176 | }; 177 | 178 | template 179 | typename result(A)>::type 180 | operator()(A& value) const 181 | { 182 | typename boost::remove_const::type res(value); 183 | return --res; 184 | } 185 | }; 186 | 187 | template<> 188 | struct functor_of 189 | { 190 | template struct result; 191 | 192 | template 193 | struct result 194 | { 195 | typedef A type; 196 | }; 197 | 198 | template 199 | typename result(A)>::type 200 | operator()(A& value) const 201 | { 202 | typename boost::remove_const::type res(value); 203 | return res++; 204 | } 205 | }; 206 | 207 | template<> 208 | struct functor_of 209 | { 210 | template struct result; 211 | 212 | template 213 | struct result 214 | { 215 | typedef A type; 216 | }; 217 | 218 | template 219 | typename result(A)>::type 220 | operator()(A& value) const 221 | { 222 | typename boost::remove_const::type res(value); 223 | return res--; 224 | } 225 | }; 226 | 227 | 228 | template<> 229 | struct functor_of 230 | { 231 | template struct result; 232 | 233 | template 234 | struct result 235 | { 236 | typedef A type; 237 | }; 238 | 239 | template 240 | typename result(A,B)>::type 241 | operator()(const A& lhs, const B& rhs) const 242 | { 243 | return lhs< 248 | struct functor_of 249 | { 250 | template struct result; 251 | 252 | template 253 | struct result 254 | { 255 | typedef A type; 256 | }; 257 | 258 | template 259 | typename result(A,B)>::type 260 | operator()(const A& lhs, const B& rhs) const 261 | { 262 | return lhs>>rhs; 263 | } 264 | }; 265 | 266 | template<> 267 | struct functor_of 268 | { 269 | template struct result; 270 | 271 | template 272 | struct result 273 | { 274 | typedef typename boost::common_type::type type; 275 | }; 276 | 277 | template 278 | typename result(A,B)>::type 279 | operator()(const A& lhs, const B& rhs) const 280 | { 281 | return lhs*rhs; 282 | } 283 | }; 284 | 285 | template<> 286 | struct functor_of 287 | { 288 | template struct result; 289 | 290 | template 291 | struct result 292 | { 293 | typedef typename boost::common_type::type type; 294 | }; 295 | 296 | template 297 | typename result(A,B)>::type 298 | operator()(const A& lhs, const B& rhs) const 299 | { 300 | return lhs/rhs; 301 | } 302 | }; 303 | 304 | template<> 305 | struct functor_of 306 | { 307 | template struct result; 308 | 309 | template 310 | struct result 311 | { 312 | typedef typename boost::common_type::type type; 313 | }; 314 | 315 | template 316 | typename result(A,B)>::type 317 | operator()(const A& lhs, const B& rhs) const 318 | { 319 | return lhs%rhs; 320 | } 321 | }; 322 | 323 | template<> 324 | struct functor_of 325 | { 326 | template struct result; 327 | 328 | template 329 | struct result 330 | { 331 | typedef typename boost::common_type::type type; 332 | }; 333 | 334 | template 335 | typename result(A,B)>::type 336 | operator()(const A& lhs, const B& rhs) const 337 | { 338 | return lhs+rhs; 339 | } 340 | }; 341 | 342 | template<> 343 | struct functor_of 344 | { 345 | template struct result; 346 | 347 | template 348 | struct result 349 | { 350 | typedef typename boost::common_type::type type; 351 | }; 352 | 353 | template 354 | typename result(A,B)>::type 355 | operator()(const A& lhs, const B& rhs) const 356 | { 357 | return lhs-rhs; 358 | } 359 | }; 360 | 361 | template<> 362 | struct functor_of 363 | { 364 | template struct result; 365 | 366 | template 367 | struct result 368 | { 369 | typedef bool type; 370 | }; 371 | 372 | template 373 | typename result(A,B)>::type 374 | operator()(const A& lhs, const B& rhs) const 375 | { 376 | return lhs 381 | struct functor_of 382 | { 383 | template struct result; 384 | 385 | template 386 | struct result 387 | { 388 | typedef bool type; 389 | }; 390 | 391 | template 392 | typename result(A,B)>::type 393 | operator()(const A& lhs, const B& rhs) const 394 | { 395 | return lhs>rhs; 396 | } 397 | }; 398 | 399 | template<> 400 | struct functor_of 401 | { 402 | template struct result; 403 | 404 | template 405 | struct result 406 | { 407 | typedef bool type; 408 | }; 409 | 410 | template 411 | typename result(A,B)>::type 412 | operator()(const A& lhs, const B& rhs) const 413 | { 414 | return lhs<=rhs; 415 | } 416 | }; 417 | 418 | template<> 419 | struct functor_of 420 | { 421 | template struct result; 422 | 423 | template 424 | struct result 425 | { 426 | typedef bool type; 427 | }; 428 | 429 | template 430 | typename result(A,B)>::type 431 | operator()(const A& lhs, const B& rhs) const 432 | { 433 | return lhs>=rhs; 434 | } 435 | }; 436 | 437 | template<> 438 | struct functor_of 439 | { 440 | template struct result; 441 | 442 | template 443 | struct result 444 | { 445 | typedef bool type; 446 | }; 447 | 448 | template 449 | typename result(A,B)>::type 450 | operator()(const A& lhs, const B& rhs) const 451 | { 452 | return lhs==rhs; 453 | } 454 | }; 455 | 456 | template<> 457 | struct functor_of 458 | { 459 | template struct result; 460 | 461 | template 462 | struct result 463 | { 464 | typedef bool type; 465 | }; 466 | 467 | template 468 | typename result(A,B)>::type 469 | operator()(const A& lhs, const B& rhs) const 470 | { 471 | return lhs!=rhs; 472 | } 473 | }; 474 | 475 | template<> 476 | struct functor_of 477 | { 478 | template struct result; 479 | 480 | template 481 | struct result 482 | { 483 | typedef bool type; 484 | }; 485 | 486 | template 487 | typename result(A,B)>::type 488 | operator()(const A& lhs, const B& rhs) const 489 | { 490 | return lhs||rhs; 491 | } 492 | }; 493 | 494 | template<> 495 | struct functor_of 496 | { 497 | template struct result; 498 | 499 | template 500 | struct result 501 | { 502 | typedef bool type; 503 | }; 504 | 505 | template 506 | typename result(A,B)>::type 507 | operator()(const A& lhs, const B& rhs) const 508 | { 509 | return lhs&&rhs; 510 | } 511 | }; 512 | 513 | template<> 514 | struct functor_of 515 | { 516 | template struct result; 517 | 518 | template 519 | struct result 520 | { 521 | typedef typename boost::common_type::type type; 522 | }; 523 | 524 | template 525 | typename result(A,B)>::type 526 | operator()(const A& lhs, const B& rhs) const 527 | { 528 | return lhs|rhs; 529 | } 530 | }; 531 | 532 | template<> 533 | struct functor_of 534 | { 535 | template struct result; 536 | 537 | template 538 | struct result 539 | { 540 | typedef typename boost::common_type::type type; 541 | }; 542 | 543 | template 544 | typename result(A,B)>::type 545 | operator()(const A& lhs, const B& rhs) const 546 | { 547 | return lhs&rhs; 548 | } 549 | }; 550 | 551 | template<> 552 | struct functor_of 553 | { 554 | template struct result; 555 | 556 | template 557 | struct result 558 | { 559 | typedef typename boost::common_type::type type; 560 | }; 561 | 562 | template 563 | typename result(A,B)>::type 564 | operator()(const A& lhs, const B& rhs) const 565 | { 566 | return lhs^rhs; 567 | } 568 | }; 569 | 570 | template<> 571 | struct functor_of 572 | { 573 | template struct result; 574 | 575 | template 576 | struct result 577 | { 578 | typedef B type; 579 | }; 580 | 581 | template 582 | typename result(A,B)>::type 583 | operator()(const A& lhs, const B& rhs) const 584 | { 585 | return lhs,rhs; 586 | } 587 | }; 588 | 589 | 590 | template<> 591 | struct functor_of 592 | { 593 | template struct result; 594 | 595 | template 596 | struct result 597 | { 598 | typedef A type; 599 | }; 600 | 601 | template 602 | typename result(A,B)>::type 603 | operator()(A& lhs, const B& rhs) const 604 | { 605 | typename boost::remove_const::type dummy(lhs); 606 | return dummy=rhs; 607 | } 608 | }; 609 | 610 | template<> 611 | struct functor_of 612 | { 613 | template struct result; 614 | 615 | template 616 | struct result 617 | { 618 | typedef A type; 619 | }; 620 | 621 | template 622 | typename result(A,B)>::type 623 | operator()(A& lhs, const B& rhs) const 624 | { 625 | typename boost::remove_const::type dummy(lhs); 626 | return dummy <<= rhs; 627 | } 628 | }; 629 | 630 | template<> 631 | struct functor_of 632 | { 633 | template struct result; 634 | 635 | template 636 | struct result 637 | { 638 | typedef A type; 639 | }; 640 | 641 | template 642 | typename result(A,B)>::type 643 | operator()(A& lhs, const B& rhs) const 644 | { 645 | typename boost::remove_const::type dummy(lhs); 646 | return dummy >>= rhs; 647 | } 648 | }; 649 | 650 | template<> 651 | struct functor_of 652 | { 653 | template struct result; 654 | 655 | template 656 | struct result 657 | { 658 | typedef A type; 659 | }; 660 | 661 | template 662 | typename result(A,B)>::type 663 | operator()(A& lhs, const B& rhs) const 664 | { 665 | typename boost::remove_const::type dummy(lhs); 666 | return dummy*=rhs; 667 | } 668 | }; 669 | 670 | template<> 671 | struct functor_of 672 | { 673 | template struct result; 674 | 675 | template 676 | struct result 677 | { 678 | typedef A type; 679 | }; 680 | 681 | template 682 | typename result(A,B)>::type 683 | operator()(A& lhs, const B& rhs) const 684 | { 685 | typename boost::remove_const::type dummy(lhs); 686 | return dummy/=rhs; 687 | } 688 | }; 689 | 690 | template<> 691 | struct functor_of 692 | { 693 | template struct result; 694 | 695 | template 696 | struct result 697 | { 698 | typedef A type; 699 | }; 700 | 701 | template 702 | typename result(A,B)>::type 703 | operator()(A& lhs, const B& rhs) const 704 | { 705 | typename boost::remove_const::type dummy(lhs); 706 | return dummy%=rhs; 707 | } 708 | }; 709 | 710 | template<> 711 | struct functor_of 712 | { 713 | template struct result; 714 | 715 | template 716 | struct result 717 | { 718 | typedef A type; 719 | }; 720 | 721 | template 722 | typename result(A,B)>::type 723 | operator()(A& lhs, const B& rhs) const 724 | { 725 | typename boost::remove_const::type dummy(lhs); 726 | return dummy+=rhs; 727 | } 728 | }; 729 | 730 | template<> 731 | struct functor_of 732 | { 733 | template struct result; 734 | 735 | template 736 | struct result 737 | { 738 | typedef A type; 739 | }; 740 | 741 | template 742 | typename result(A,B)>::type 743 | operator()(A& lhs, const B& rhs) const 744 | { 745 | typename boost::remove_const::type dummy(lhs); 746 | return dummy-=rhs; 747 | } 748 | }; 749 | 750 | template<> 751 | struct functor_of 752 | { 753 | template struct result; 754 | 755 | template 756 | struct result 757 | { 758 | typedef A type; 759 | }; 760 | 761 | template 762 | typename result(A,B)>::type 763 | operator()(A& lhs, const B& rhs) const 764 | { 765 | typename boost::remove_const::type dummy(lhs); 766 | return dummy&=rhs; 767 | } 768 | }; 769 | 770 | template<> 771 | struct functor_of 772 | { 773 | template struct result; 774 | 775 | template 776 | struct result 777 | { 778 | typedef A type; 779 | }; 780 | 781 | template 782 | typename result(A,B)>::type 783 | operator()(A& lhs, const B& rhs) const 784 | { 785 | typename boost::remove_const::type dummy(lhs); 786 | return dummy|=rhs; 787 | } 788 | }; 789 | 790 | 791 | template<> 792 | struct functor_of 793 | { 794 | template struct result; 795 | 796 | template 797 | struct result 798 | { 799 | typedef A type; 800 | }; 801 | 802 | template 803 | typename result(A,B)>::type 804 | operator()(A& lhs, const B& rhs) const 805 | { 806 | typename boost::remove_const::type dummy(lhs); 807 | return dummy^=rhs; 808 | } 809 | }; 810 | 811 | 812 | template<> 813 | struct functor_of 814 | { 815 | template struct result; 816 | 817 | template 818 | struct result 819 | { 820 | // TODO: this will work for arrays but not in general. fix or remove. 821 | typedef typename boost::remove_pointer::type type; 822 | }; 823 | 824 | template 825 | typename result(A,B)>::type 826 | operator()(const A& array, const B& index) const 827 | { 828 | return array[index]; 829 | } 830 | }; 831 | 832 | 833 | template<> 834 | struct functor_of 835 | { 836 | template struct result; 837 | 838 | template 839 | struct result 840 | { 841 | typedef typename boost::common_type::type type; 842 | }; 843 | 844 | template 845 | typename result(A,B,C)>::type 846 | operator()(const A& condition, const B& yes, const C& no) 847 | { 848 | return condition ? yes : no; 849 | } 850 | }; 851 | 852 | } // ns streamulus 853 | --------------------------------------------------------------------------------