From 257962b6bb97ab27762bde93eda82223fdf464d6 Mon Sep 17 00:00:00 2001 From: stdlib-bot Date: Tue, 15 Jun 2021 14:47:36 -0400 Subject: [PATCH] Auto-generated commit --- .editorconfig | 154 +++++++ .gitattributes | 33 ++ .github/PULL_REQUEST_TEMPLATE.md | 7 + .github/workflows/benchmark.yml | 19 + .github/workflows/close_pull_requests.yml | 23 + .github/workflows/examples.yml | 19 + .github/workflows/publish.yml | 34 ++ .github/workflows/test.yml | 29 ++ .github/workflows/test_coverage.yml | 24 + .github/workflows/test_install.yml | 27 ++ .gitignore | 181 ++++++++ .npmignore | 225 +++++++++ .npmrc | 28 ++ CODE_OF_CONDUCT.md | 3 + CONTRIBUTING.md | 3 + CONTRIBUTORS | 24 + LICENSE | 481 +++++++++++++++++++ Makefile | 534 ++++++++++++++++++++++ NOTICE | 1 + README.md | 210 +++++++++ benchmark/benchmark.js | 94 ++++ benchmark/benchmark.object.js | 77 ++++ benchmark/benchmark.preallocation.js | 138 ++++++ benchmark/benchmark.typed_array.js | 246 ++++++++++ docs/repl.txt | 46 ++ docs/types/index.d.ts | 57 +++ docs/types/test.ts | 51 +++ examples/index.js | 35 ++ lib/index.js | 49 ++ lib/prepend.js | 85 ++++ lib/prepend_array.js | 48 ++ lib/prepend_object.js | 64 +++ lib/prepend_typed_array.js | 90 ++++ package.json | 117 +++++ test/test.js | 357 +++++++++++++++ 35 files changed, 3613 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workflows/benchmark.yml create mode 100644 .github/workflows/close_pull_requests.yml create mode 100644 .github/workflows/examples.yml create mode 100644 .github/workflows/publish.yml create mode 100644 .github/workflows/test.yml create mode 100644 .github/workflows/test_coverage.yml create mode 100644 .github/workflows/test_install.yml create mode 100644 .gitignore create mode 100644 .npmignore create mode 100644 .npmrc create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 CONTRIBUTORS create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 NOTICE create mode 100644 README.md create mode 100644 benchmark/benchmark.js create mode 100644 benchmark/benchmark.object.js create mode 100644 benchmark/benchmark.preallocation.js create mode 100644 benchmark/benchmark.typed_array.js create mode 100644 docs/repl.txt create mode 100644 docs/types/index.d.ts create mode 100644 docs/types/test.ts create mode 100644 examples/index.js create mode 100644 lib/index.js create mode 100644 lib/prepend.js create mode 100644 lib/prepend_array.js create mode 100644 lib/prepend_object.js create mode 100644 lib/prepend_typed_array.js create mode 100644 package.json create mode 100644 test/test.js diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c66ad55 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,154 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2017 The Stdlib Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#/ + +# EditorConfig configuration file (see ). + +# Indicate that this file is a root-level configuration file: +root = true + +# Set properties for all files: +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +# Set properties for JavaScript files: +[*.js] +indent_style = tab + +# Set properties for TypeScript files: +[*.ts] +indent_style = tab + +# Set properties for Python files: +[*.py] +indent_style = space +indent_size = 4 + +# Set properties for Julia files: +[*.jl] +indent_style = tab + +# Set properties for R files: +[*.R] +indent_style = tab + +# Set properties for C files: +[*.c] +indent_style = tab + +# Set properties for C header files: +[*.h] +indent_style = tab + +# Set properties for C++ files: +[*.cpp] +indent_style = tab + +# Set properties for C++ header files: +[*.hpp] +indent_style = tab + +# Set properties for Fortran files: +[*.f] +indent_style = space +indent_size = 2 +insert_final_newline = false + +# Set properties for shell files: +[*.sh] +indent_style = tab + +# Set properties for AWK files: +[*.awk] +indent_style = tab + +# Set properties for HTML files: +[*.html] +indent_style = tab +tab_width = 2 + +# Set properties for CSS files: +[*.css] +indent_style = tab + +# Set properties for Makefiles: +[Makefile] +indent_style = tab + +[*.mk] +indent_style = tab + +# Set properties for Markdown files: +[*.md] +indent_style = space +indent_size = 4 +trim_trailing_whitespace = false + +# Set properties for `usage.txt` files: +[usage.txt] +indent_style = space +indent_size = 2 + +# Set properties for `repl.txt` files: +[repl.txt] +indent_style = space +indent_size = 4 + +# Set properties for `package.json` files: +[package.json] +indent_style = space +indent_size = 2 + +# Set properties for `datapackage.json` files: +[datapackage.json] +indent_style = space +indent_size = 2 + +# Set properties for `tslint.json` files: +[tslint.json] +indent_style = space +indent_size = 2 + +# Set properties for `tsconfig.json` files: +[tsconfig.json] +indent_style = space +indent_size = 2 + +# Set properties for LaTeX files: +[*.tex] +indent_style = tab + +# Set properties for LaTeX Bibliography files: +[*.bib] +indent_style = tab + +# Set properties for YAML files: +[*.yml] +indent_style = space +indent_size = 2 + +# Set properties for GYP files: +[binding.gyp] +indent_style = space +indent_size = 2 + +[*.gypi] +indent_style = space +indent_size = 2 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..7212d81 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,33 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2017 The Stdlib Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#/ + +# Configuration file which assigns attributes to pathnames. +# +# [1]: https://git-scm.com/docs/gitattributes + +# Automatically normalize the line endings of any committed text files: +* text=auto + +# Override what is considered "vendored" by GitHub's linguist: +/deps/** linguist-vendored=false +/lib/node_modules/** linguist-vendored=false linguist-generated=false +test/fixtures/** linguist-vendored=false +tools/** linguist-vendored=false + +# Override what is considered "documentation" by GitHub's linguist: +examples/** linguist-documentation=false diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..5b0377e --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,7 @@ + + +We are excited about your pull request, but unfortunately we are not accepting pull requests against this repository, as all development happens on the [main project repository](https://github.com/stdlib-js/stdlib). We kindly request that you submit this pull request against the [respective directory](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/utils/prepend) of the main repository where we’ll review and provide feedback. + +If this is your first stdlib contribution, be sure to read the [contributing guide](https://github.com/stdlib-js/stdlib/blob/develop/CONTRIBUTING.md) which provides guidelines and instructions for submitting contributions. You may also consult the [development guide](https://github.com/stdlib-js/stdlib/blob/develop/docs/development.md) for help on developing stdlib. + +We look forward to receiving your contribution! :smiley: \ No newline at end of file diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml new file mode 100644 index 0000000..e51e34e --- /dev/null +++ b/.github/workflows/benchmark.yml @@ -0,0 +1,19 @@ +name: benchmark + +on: + workflow_dispatch: + +jobs: + benchmark: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: 15 + - name: Install production and development dependencies + run: | + npm install + - name: Run benchmarks + run: | + npm run benchmark diff --git a/.github/workflows/close_pull_requests.yml b/.github/workflows/close_pull_requests.yml new file mode 100644 index 0000000..88edad6 --- /dev/null +++ b/.github/workflows/close_pull_requests.yml @@ -0,0 +1,23 @@ +name: Close Pull Requests + +on: + pull_request_target: + types: [opened] + +jobs: + run: + runs-on: ubuntu-latest + steps: + - uses: superbrothers/close-pull-request@v3 + with: + comment: | + Thank you for submitting a pull request. :raised_hands: + + We greatly appreciate your willingness to submit a contribution. However, we are not accepting pull requests against this repository, as all development happens on the [main project repository](https://github.com/stdlib-js/stdlib). + + We kindly request that you submit this pull request against the [respective directory](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/utils/prepend) of the main repository where we’ll review and provide feedback. If this is your first stdlib contribution, be sure to read the [contributing guide](https://github.com/stdlib-js/stdlib/blob/develop/CONTRIBUTING.md) which provides guidelines and instructions for submitting contributions. + + Thank you again, and we look forward to receiving your contribution! :smiley: + + Best, + The stdlib team \ No newline at end of file diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml new file mode 100644 index 0000000..0c19f10 --- /dev/null +++ b/.github/workflows/examples.yml @@ -0,0 +1,19 @@ +name: examples + +on: + workflow_dispatch: + +jobs: + examples: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: 15 + - name: Install production and development dependencies + run: | + npm install + - name: Run examples + run: | + npm run examples diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..ae05f51 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,34 @@ +name: Publish Package + +on: push + +jobs: + publish: + runs-on: ubuntu-latest + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: 15 + - name: Increment version + run: | + git config --local user.email "noreply@stdlib.io" + git config --local user.name "stdlib-bot" + npm version patch + - name: Publish package to npm + uses: JS-DevTools/npm-publish@v1 + with: + token: ${{ secrets.NPM_TOKEN }} + access: public + - name: Push changes + run: | + git push origin main + git push --tags + - uses: act10ns/slack@v1 + with: + status: ${{ job.status }} + steps: ${{ toJson(steps) }} + channel: '#npm-ci' + if: failure() diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..3c99108 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,29 @@ +name: build + +on: + workflow_dispatch: + +jobs: + test: + runs-on: ubuntu-latest + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: 15 + - name: Install production and development dependencies + id: install + run: | + npm install + - name: Run tests + id: tests + run: | + npm test + - uses: act10ns/slack@v1 + with: + status: ${{ job.status }} + steps: ${{ toJson(steps) }} + channel: '#npm-ci' + if: failure() diff --git a/.github/workflows/test_coverage.yml b/.github/workflows/test_coverage.yml new file mode 100644 index 0000000..0e8045d --- /dev/null +++ b/.github/workflows/test_coverage.yml @@ -0,0 +1,24 @@ +name: coverage + +on: + workflow_dispatch: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: 15 + - name: Install production and development dependencies + run: | + npm install + - name: Calculate test coverage + run: | + npm run test-cov + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v1 + with: + directory: reports/coverage + flags: unittests diff --git a/.github/workflows/test_install.yml b/.github/workflows/test_install.yml new file mode 100644 index 0000000..ee70831 --- /dev/null +++ b/.github/workflows/test_install.yml @@ -0,0 +1,27 @@ +name: Test Installing Dependencies + +on: + workflow_run: + workflows: ["Publish Package"] + types: [completed] + +jobs: + on-success: + runs-on: ubuntu-latest + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + if: ${{ github.event.workflow_run.conclusion == 'success' }} + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: 15 + - name: Install production dependencies via npm + run: | + npm install --only=prod + - uses: act10ns/slack@v1 + with: + status: ${{ job.status }} + steps: ${{ toJson(steps) }} + channel: '#npm-ci' + if: failure() diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1475963 --- /dev/null +++ b/.gitignore @@ -0,0 +1,181 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2017 The Stdlib Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#/ + +# Files # +######### +.postinstall.json + +# Directories # +############### +build/ +downloads/ +reports/ +tmp/ + +# Compiled source # +################### +*.com +*.class +*.dll +*.o +*.so +*.slo +*.lo +*.obj +*.dylib +*.lai +*.la +*.a +*.lib +*.ko +*.elf +*.node + +# Precompiled headers # +####################### +*.gch +*.pch + +# Executables # +############### +*.exe +*.out +*.app + +# Packages # +############ +# It is better to unpack these files and commit the raw source +# git has its own built in compression methods +*.7z +*.dmg +*.gz +*.iso +*.jar +*.rar +*.tar +*.zip + +# Make an exception for compressed distributable files: +!dist/*.gz + +# Logs and databases # +###################### +*.log +*.sql +*.sqlite + +# OS generated files # +###################### +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +Icon? +ehthumbs.db +Thumbs.db +Desktop.ini + +# Temporary files # +################### +*~ + +# Node.js # +########### +/node_modules/ +lib/node_modules/**/node_modules/ +docs/**/node_modules/ +pids +*.pid +*.seed + +# Typescript # +############## +*.tsbuildinfo +lib/node_modules/**/tsconfig.json +lib/node_modules/**/tslint.json + +# Matlab # +########## +*.asv +*.mex* + +# Fortran # +########### +*.mod + +# R # +##### +.Rhistory +.Rapp.history +.Rproj.user/ + +# Python # +########## +__pycache__/ +*.py[cod] +*$py.class +*.egg-info/ + +# TeX # +####### +*.aux +*.lof +*.log +*.lot +*.fls +*.out +*.toc +*.dvi +*-converted-to.* +*.bbl +*.bcf +*.blg +*-blx.aux +*-blx.bib +*.brf +*.run.xml +*.fdb_latexmk +*.synctex +*.synctex.gz +*.synctex.gz(busy) +*.pdfsync +*.alg +*.loa +acs-*.bib +*.thm +*.nav +*.snm +*.vrb +*.acn +*.acr +*.glg +*.glo +*.gls +*-concordance.tex +*.tikz +*-tikzDictionary +*.idx +*.ilg +*.ind +*.ist + +# Visual Studio # +################# +.vscode/ +jsconfig.json diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..401aa76 --- /dev/null +++ b/.npmignore @@ -0,0 +1,225 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2017 The Stdlib Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#/ + +# Files # +######### +CODE_OF_CONDUCT.md +CONTRIBUTING.md +CONTRIBUTORS +TODO.md +ROADMAP.md +.postinstall.json + +# Directories # +############### +.circleci/ +.github/ +**/benchmark/ +**/build/ +**/examples/ +reports/ +support/ +**/tmp/ +workshops/ + +# Ignore test directories, except for testing dependency installation: +**/test/ +!/deps/test/ + +# Only top-level directories: +/etc/ +/docs/ + +# Compiled source # +################### +*.com +*.class +*.dll +*.o +*.so +*.slo +*.lo +*.obj +*.dylib +*.lai +*.la +*.a +*.lib +*.ko +*.elf +*.node + +# Precompiled headers # +####################### +*.gch +*.pch + +# Executables # +############### +*.exe +*.out +*.app + +# Packages # +############ +*.7z +*.dmg +*.gz +*.iso +*.jar +*.rar +*.tar +*.zip + +# Make an exception for compressed distributable files: +!dist/*.gz + +# Logs and databases # +###################### +*.log +*.sql +*.sqlite + +# OS generated files # +###################### +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +Icon? +ehthumbs.db +Thumbs.db +Desktop.ini + +# Temporary files # +################### +*~ + +# Node.js # +########### +.npmignore + +# Only top-level node_modules: +/node_modules/ + +# TypeScript # +############## +tsconfig.json +tslint.json +*.tsbuildinfo + +# Matlab # +########## +*.asv +*.mex* + +# Fortran # +########### +*.mod + +# R # +##### +.Rhistory +.Rapp.history +.Rproj.user/ + +# Python # +########## +__pycache__/ +*.py[cod] +*$py.class +*.egg-info/ +.ipynb_checkpoints +setup.cfg +setup.py + +# TeX # +####### +*.aux +*.lof +*.log +*.lot +*.fls +*.out +*.toc +*.dvi +*-converted-to.* +*.bbl +*.bcf +*.blg +*-blx.aux +*-blx.bib +*.brf +*.run.xml +*.fdb_latexmk +*.synctex +*.synctex.gz +*.synctex.gz(busy) +*.pdfsync +*.alg +*.loa +acs-*.bib +*.thm +*.nav +*.snm +*.vrb +*.acn +*.acr +*.glg +*.glo +*.gls +*-concordance.tex +*.tikz +*-tikzDictionary +*.idx +*.ilg +*.ind +*.ist + +# Git # +####### +.git* +.mailmap + +# Visual Studio # +################# +.vscode/ +jsconfig.json + +# Utilities # +############# +.jshintrc +.jshintignore +.eslintrc* +.eslintignore + +.pylintrc +.pycodestyle +.pydocstyle + +.travis.yml +circle.yml +appveyor.yml +azure-pipelines.yml + +.editorconfig +.codeclimate.yml +.codecov.yml + +.rtlintrc diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..36f5bef --- /dev/null +++ b/.npmrc @@ -0,0 +1,28 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2017 The Stdlib Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#/ + +# Configuration for [npm][1]. +# +# [1]: https://docs.npmjs.com/files/npmrc + +# Disable the creation of a lock file: +package-lock = false +shrinkwrap = false + +# Disable automatically "saving" dependencies on install: +save = false diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..35b70c9 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,3 @@ +# Code of Conduct + +stdlib expects community participants to adhere to the project Code of Conduct. The [full text](https://github.com/stdlib-js/stdlib/blob/develop/CODE_OF_CONDUCT.md) is available in the main project repository. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..5f59443 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +# Contribution Guidelines + +Woot woot! If you are new to stdlib, welcome! And thanks for your interest! Guidelines for how to contribute to the project are [available](https://github.com/stdlib-js/stdlib/blob/develop/CONTRIBUTING.md) in the main project repository. diff --git a/CONTRIBUTORS b/CONTRIBUTORS new file mode 100644 index 0000000..da469e5 --- /dev/null +++ b/CONTRIBUTORS @@ -0,0 +1,24 @@ +# This file is generated by tools/scripts/update_contributors. +# +# Contributors listed in alphabetical order. + +Athan Reines +Brendan Graetz +Bruno Fenzl +Christopher Dambamuromo +Dominik Moritz +Frank Kovacs +James +Jithin KS +Joey Reed +Joris Labie +Justin Dennison +Marcus +Matt Cochrane +Milan Raj +Ognjen Jevremović +Philipp Burckhardt +Ricky Reusser +Ryan Seal +Shraddheya Shendre +rei2hu diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fcc9934 --- /dev/null +++ b/LICENSE @@ -0,0 +1,481 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by this +license (the "Software") to use, reproduce, display, distribute, execute, and +transmit the Software, and to prepare derivative works of the Software, and to +permit third-parties to whom the Software is furnished to do so, all subject to +the following: + +The copyright notices in the Software and this entire statement, including the +above license grant, this restriction and the following disclaimer, must be +included in all copies of the Software, in whole or in part, and all derivative +works of the Software, unless such copies or derivative works are solely in the +form of machine-executable object code generated by a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES +OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + + +DEPENDENCIES + +The library links against the following external libraries, which have their own +licenses: + +* OpenBLAS + +Copyright (c) 2011-2014, The OpenBLAS Project +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + 3. Neither the name of the OpenBLAS project nor the names of + its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +* Electron + +Copyright (c) 2013-2017 GitHub Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +* Boost + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + + +* Cephes + +Copyright (c) 1984-2000 Stephen L. Moshier + +Some software in this archive may be from the book _Methods and Programs for +Mathematical Functions_ (Prentice-Hall or Simon & Schuster International, 1989) +or from the Cephes Mathematical Library, a commercial product. In either event, +it is copyrighted by the author. What you see here may be used freely but it +comes with no support or guarantee. + +Stephen L. Moshier +moshier@na-net.ornl.gov + + + +ATTRIBUTION + +The library contains implementations from the following external libraries, +which have their own licenses: + +* FreeBSD + +Copyright (C) 1993-2004 by Sun Microsystems, Inc. All rights reserved. + +Developed at SunPro, a Sun Microsystems, Inc. business. +Permission to use, copy, modify, and distribute this +software is freely granted, provided that this notice +is preserved. + + +* FDLIBM + +Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. + +Developed at SunPro, a Sun Microsystems, Inc. business. +Permission to use, copy, modify, and distribute this +software is freely granted, provided that this notice +is preserved. + + +* Go + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +* SLATEC Common Mathematical Library + +Public domain. + + +* ESLint + +Copyright JS Foundation and other contributors, https://js.foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +* StatsFuns.jl + +Copyright (c) 2015: Dahua Lin. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +* SpecialFunctions.jl + +The MIT License (MIT) + +Copyright (c) 2017 Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and others: + +https://github.com/JuliaMath/SpecialFunctions.jl/graphs/contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +* MT19937 + +Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1c7d53e --- /dev/null +++ b/Makefile @@ -0,0 +1,534 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2021 The Stdlib Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#/ + +# USER VARIABLES # + +ifndef VERBOSE + QUIET := @ +else + QUIET := +endif + +# Indicate whether to "fast" fail when linting, running tests, etc: +ifndef FAST_FAIL + FAIL_FAST := true +else +ifeq ($(FAST_FAIL), 0) + FAIL_FAST := false +else + FAIL_FAST := true +endif +endif + +# Define the `NODE_PATH` environment variable: +NODE_PATH ?= + +# Define the `NODE_ENV` environment variable: +NODE_ENV ?= + + +# INTERNAL VARIABLES # + +# Instruct make to warn us when we use an undefined variable (e.g., misspellings). +MAKEFLAGS += --warn-undefined-variables + +# Define the default target: +.DEFAULT_GOAL := all + +# Define the `SHELL` variable to avoid issues on systems where the variable may be inherited from the environment. +# +# ## Notes +# +# - We use `bash` so that we can use `pipefail`. +# +# +# [1]: https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html#Makefile-Basics +# [2]: http://clarkgrubb.com/makefile-style-guide +SHELL := bash + +# Define shell flags. +# +# ## Notes +# +# - `.SHELLFLAGS` was introduced in GNU Make 3.82 and has no effect on the version of GNU Make installed on Mac OS X, which is 3.81. +# - The `-e` flag causes `bash` to exit immediately if a `bash` executed command fails. +# - The `-u` flag causes `bash` to exit with an error message if a variable is accessed without being defined. +# - The `pipefail` option specifies that, if any of the commands in a pipeline fail, the entire pipeline fails. Otherwise the return value of a pipeline is the return value of the last command. +# - The `-c` flag is in the default value of `.SHELLFLAGS`, which must be preserved, as this is how `make` passes the script to be executed to `bash`. +# +.SHELLFLAGS := -eu -o pipefail -c + +# Remove targets if its recipe fails. +# +# ## Notes +# +# - Mentioning this target anywhere in a Makefile prevents a user from re-running make and using an incomplete or invalid target. +# - When debugging, it may be necessary to comment this line out so the incomplete or invalid target can be inspected. +# +# [1]: https://www.gnu.org/software/make/manual/html_node/Special-Targets.html +.DELETE_ON_ERROR: + +# Remove all the default suffixes, preferring to define all rules explicitly. +# +# [1]: https://www.gnu.org/software/make/manual/html_node/Suffix-Rules.html#Suffix-Rules +# [2]: https://www.gnu.org/software/make/manual/html_node/Suffix-Rules.html#Suffix-Rules +.SUFFIXES: + +# Determine the OS ([1][1], [2][2]). +# +# [1]: https://en.wikipedia.org/wiki/Uname#Examples +# [2]: http://stackoverflow.com/a/27776822/2225624 +OS ?= $(shell uname) +ifneq (, $(findstring MINGW,$(OS))) + OS := WINNT +else +ifneq (, $(findstring MSYS,$(OS))) + OS := WINNT +else +ifneq (, $(findstring CYGWIN,$(OS))) + OS := WINNT +else +ifneq (, $(findstring Windows_NT,$(OS))) + OS := WINNT +endif +endif +endif +endif + +# Determine the filename: +this_file := $(lastword $(MAKEFILE_LIST)) + +# Determine the absolute path of the Makefile (see http://blog.jgc.org/2007/01/what-makefile-am-i-in.html): +this_dir := $(dir $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))) + +# Remove the trailing slash: +this_dir := $(patsubst %/,%,$(this_dir)) + +# Determine root directory: +ROOT_DIR = $(this_dir) + +# Define the root build directory: +BUILD_DIR ?= $(ROOT_DIR)/build + +# Define the root directory for storing distributable files: +DIST_DIR ?= $(ROOT_DIR)/dist + +# Define the root directory for storing temporary files: +TMP_DIR ?= $(ROOT_DIR)/tmp + +# Define the directories for writing reports, including code coverage: +REPORTS_DIR ?= $(ROOT_DIR)/reports +COVERAGE_DIR ?= $(REPORTS_DIR)/coverage + +# Define the top-level directory containing node module dependencies: +NODE_MODULES ?= $(ROOT_DIR)/node_modules + +# Define the top-level directory containing node module executables: +BIN_DIR ?= $(NODE_MODULES)/.bin + +# Define the path to the root `package.json`: +ROOT_PACKAGE_JSON ?= $(ROOT_DIR)/package.json + +# Define the folder name convention for source files requiring compilation: +SRC_FOLDER ?= src + +# Define the folder name convention for documentation files: +DOCUMENTATION_FOLDER ?= docs + +# Define the folder name convention for configuration files: +CONFIG_FOLDER ?= etc + +# Define the folder name convention for benchmark files: +BENCHMARKS_FOLDER ?= benchmark + +# Define the folder name convention for benchmark fixtures: +BENCHMARKS_FIXTURES_FOLDER ?= $(BENCHMARKS_FOLDER)/fixtures + +# Define the folder name convention for examples files: +EXAMPLES_FOLDER ?= examples + +# Define the folder name convention for examples fixtures: +EXAMPLES_FIXTURES_FOLDER ?= $(EXAMPLES_FOLDER)/fixtures + +# Define the folder name convention for test files: +TESTS_FOLDER ?= test + +# Define the folder name convention for test fixtures: +TESTS_FIXTURES_FOLDER ?= $(TESTS_FOLDER)/fixtures + +# Define a filepath pattern for benchmark files: +BENCHMARKS_FILTER ?= .*/.* + +# Define a filepath pattern for example files: +EXAMPLES_FILTER ?= .*/.* + +# Define a filepath pattern for test files: +TESTS_FILTER ?= .*/.* + +# Define a filename pattern for benchmark files: +BENCHMARKS_PATTERN ?= benchmark*.js + +# Define a filename pattern for example files: +EXAMPLES_PATTERN ?= *.js + +# Define a filename pattern for test files: +TESTS_PATTERN ?= test*.js + +# Define Node environments: +ifdef NODE_ENV + NODE_ENV_BENCHMARK := $(NODE_ENV) + NODE_ENV_EXAMPLES := $(NODE_ENV) + NODE_ENV_TEST := $(NODE_ENV) +else + NODE_ENV ?= + NODE_ENV_BENCHMARK ?= benchmark + NODE_ENV_EXAMPLES ?= examples + NODE_ENV_TEST ?= test +endif + +# Define whether delete operations should be safe (i.e., deleted items are sent to trash, rather than permanently deleted): +SAFE_DELETE ?= false + +# Define the delete command: +ifeq ($(SAFE_DELETE), true) + # FIXME: -rm -rf + DELETE := -rm + DELETE_FLAGS := -rf +else + DELETE ?= -rm + DELETE_FLAGS ?= -rf +endif + +# Determine the `open` command: +ifeq ($(OS), Darwin) + OPEN ?= open +else + OPEN ?= xdg-open +endif +# TODO: add Windows command + +# Define the command for `node`: +NODE ?= node + +# Define the command for `npm`: +NPM ?= npm + +# Define the path to a JavaScript test runner. +# +# ## Notes +# +# - We reference the `bin` file directly in order to support using `istanbul` for code coverage on Windows (https://github.com/gotwarlost/istanbul#usage-on-windows) +JAVASCRIPT_TEST ?= $(NODE_MODULES)/tape/bin/tape + +# Define any command-line options to use when invoking the test runner: +JAVASCRIPT_TEST_FLAGS ?= + +# Define the path to the executable for parsing TAP output: +TAP_REPORTER ?= $(BIN_DIR)/tap-spec + +# Define the path to the Istanbul executable: +ISTANBUL ?= $(BIN_DIR)/istanbul + +# Define which files and directories to exclude from coverage instrumentation: +ISTANBUL_EXCLUDES_FLAGS ?= \ + --no-default-excludes \ + -x 'node_modules/**' \ + -x 'reports/**' \ + -x 'tmp/**' \ + -x 'deps/**' \ + -x 'dist/**' \ + -x "**/$(SRC_FOLDER)/**" \ + -x "**/$(TESTS_FOLDER)/**" \ + -x "**/$(EXAMPLES_FOLDER)/**" \ + -x "**/$(BENCHMARKS_FOLDER)/**" \ + -x "**/$(CONFIG_FOLDER)/**" \ + -x "**/$(DOCUMENTATION_FOLDER)/**" + +# Define the command to generate test coverage: +ISTANBUL_COVER ?= $(ISTANBUL) cover + +# Define the type of report Istanbul should produce: +ISTANBUL_COVER_REPORT_FORMAT ?= lcov + +# Define the command-line options to be used when generating code coverage: +ISTANBUL_COVER_FLAGS ?= \ + $(ISTANBUL_EXCLUDES_FLAGS) \ + --dir $(COVERAGE_DIR) \ + --report $(ISTANBUL_COVER_REPORT_FORMAT) + +# On Mac OSX, in order to use `|` and other regular expression operators, we need to use enhanced regular expression syntax (-E); see https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man7/re_format.7.html#//apple_ref/doc/man/7/re_format. +ifeq ($(OS), Darwin) + find_kernel_prefix := -E +else + find_kernel_prefix := +endif + +# Common exclude flags that most recipes for finding package files should use (Note: order does matter to some degree): +FIND_COMMON_EXCLUDE_FLAGS ?= \ + -not -path "$(ROOT_DIR)/.*" \ + -not -path "$(NODE_MODULES)/*" \ + -not -path "$(BUILD_DIR)/*" \ + -not -path "$(REPORTS_DIR)/*" \ + +# Define exclusion flags to use when searching for benchmark files: +FIND_BENCHMARKS_EXCLUDE_FLAGS ?= \ + $(FIND_COMMON_EXCLUDE_FLAGS) \ + -not -path "$(ROOT_DIR)/**/$(BENCHMARKS_FIXTURES_FOLDER)/*" + +# Define flags for finding benchmark files: +FIND_BENCHMARKS_FLAGS ?= \ + -type f \ + -name "$(BENCHMARKS_PATTERN)" \ + -path "$(ROOT_DIR)/**/$(BENCHMARKS_FOLDER)/**" \ + -regex "$(BENCHMARKS_FILTER)" \ + $(FIND_BENCHMARKS_EXCLUDE_FLAGS) + +ifneq ($(OS), Darwin) + FIND_BENCHMARKS_FLAGS := -regextype posix-extended $(FIND_BENCHMARKS_FLAGS) +endif + +# Define a command to list benchmark files: +FIND_BENCHMARKS_CMD ?= find $(find_kernel_prefix) $(ROOT_DIR) $(FIND_BENCHMARKS_FLAGS) + +# Define exclusion flags to use when searching for examples files: +FIND_EXAMPLES_EXCLUDE_FLAGS ?= \ + $(FIND_COMMON_EXCLUDE_FLAGS) \ + -not -path "$(ROOT_DIR)/**/$(EXAMPLES_FIXTURES_FOLDER)/*" + +# Define flags for finding examples files: +FIND_EXAMPLES_FLAGS ?= \ + -type f \ + -name "$(EXAMPLES_PATTERN)" \ + -path "$(ROOT_DIR)/**/$(EXAMPLES_FOLDER)/**" \ + -regex "$(EXAMPLES_FILTER)" \ + $(FIND_EXAMPLES_EXCLUDE_FLAGS) + +ifneq ($(OS), Darwin) + FIND_EXAMPLES_FLAGS := -regextype posix-extended $(FIND_EXAMPLES_FLAGS) +endif + +# Define a command to list example files: +FIND_EXAMPLES_CMD ?= find $(find_kernel_prefix) $(ROOT_DIR) $(FIND_EXAMPLES_FLAGS) + +# Define exclusion flags to use when searching for test files: +FIND_TESTS_EXCLUDE_FLAGS ?= \ + $(FIND_COMMON_EXCLUDE_FLAGS) \ + -not -path "$(ROOT_DIR)/**/$(TESTS_FIXTURES_FOLDER)/*" + +# Define flags for finding test files: +FIND_TESTS_FLAGS ?= \ + -type f \ + -name "$(TESTS_PATTERN)" \ + -regex "$(TESTS_FILTER)" \ + $(FIND_TESTS_EXCLUDE_FLAGS) + +ifneq ($(OS), Darwin) + FIND_TESTS_FLAGS := -regextype posix-extended $(FIND_TESTS_FLAGS) +endif + +# Define a command to list test files: +FIND_TESTS_CMD ?= find $(find_kernel_prefix) $(ROOT_DIR) $(FIND_TESTS_FLAGS) + + +# RULES # + +#/ +# Default target. +# +# @example +# make +# +# @example +# make all +#/ +all: help + +.PHONY: all + +#/ +# Prints a `Makefile` help message. +# +# @example +# make help +#/ +help: + $(QUIET) echo 'Read the Makefile to see the list of available commands.' + $(QUIET) echo '' + +.PHONY: help + +#/ +# Prints the runtime value of a `Makefile` variable. +# +# ## Notes +# +# - The rule uses the following format: +# +# ```bash +# $ make inspect. +# ``` +# +# @example +# make inspect.ROOT_DIR +# +# @example +# make inspect.CC +#/ +inspect.%: + $(QUIET) echo '$*=$($*)' + +#/ +# Runs the project's install sequence. +# +# @example +# make install +#/ +install: + $(NPM) install + +.PHONY: install + +#/ +# Removes node module dependencies. +# +# @example +# make clean-node +#/ +clean-node: + $(QUIET) $(DELETE) $(DELETE_FLAGS) $(NODE_MODULES) + +#/ +# Runs the project's cleanup sequence. +# +# @example +# make clean +#/ +clean: clean-node clean-cov + $(QUIET) $(DELETE) $(DELETE_FLAGS) $(BUILD_DIR) + $(QUIET) $(DELETE) $(DELETE_FLAGS) $(REPORTS_DIR) + +.PHONY: clean + +#/ +# Runs JavaScript benchmarks consecutively. +# +# ## Notes +# +# - The recipe assumes that benchmark files can be run via Node.js. +# - This rule is useful when wanting to glob for JavaScript benchmark files (e.g., run all JavaScript benchmarks for a particular package). +# +# +# @param {string} [BENCHMARKS_FILTER] - file path pattern (e.g., `.*/utils/group-by/.*`) +# +# @example +# make benchmark +# +# @example +# make benchmark BENCHMARKS_FILTER=".*/utils/group-by/.*" +#/ +benchmark: $(NODE_MODULES) + $(QUIET) $(FIND_BENCHMARKS_CMD) | grep '^[\/]\|^[a-zA-Z]:[/\]' | while read -r file; do \ + echo ""; \ + echo "Running benchmark: $$file"; \ + NODE_ENV="$(NODE_ENV_BENCHMARK)" \ + NODE_PATH="$(NODE_PATH)" \ + $(NODE) $$file || exit 1; \ + done + +.PHONY: benchmark + +#/ +# Runs JavaScript examples consecutively. +# +# ## Notes +# +# - This rule is useful when wanting to glob for JavaScript examples files (e.g., run all JavaScript examples for a particular package). +# - This rule **assumes** that examples files can be run using Node.js. +# +# +# @param {string} [EXAMPLES_FILTER] - file path pattern (e.g., `.*/math/base/special/abs/.*`) +# +# @example +# make examples +# +# @example +# make examples EXAMPLES_FILTER=".*/strided/common/.*" +#/ +examples: $(NODE_MODULES) + $(QUIET) $(FIND_EXAMPLES_CMD) | grep '^[\/]\|^[a-zA-Z]:[/\]' | while read -r file; do \ + echo ""; \ + echo "Running example: $$file"; \ + NODE_ENV="$(NODE_ENV_EXAMPLES)" \ + NODE_PATH="$(NODE_PATH)" \ + $(NODE) $$file || exit 1; \ + done + +.PHONY: examples + +#/ +# Runs JavaScript tests consecutively. +# +# ## Notes +# +# - This rule is useful when wanting to glob for JavaScript test files (e.g., run all JavaScript tests for a particular package). +# - This rule **assumes** that test files can be run using Node.js. +# +# +# @param {string} [TEST_FILTER] - file path pattern (e.g., `.*/math/base/special/abs/.*`) +# +# @example +# make test +# +# @example +# make test TESTS_FILTER=".*/strided/common/.*" +#/ +test: $(NODE_MODULES) + $(QUIET) $(FIND_TESTS_CMD) | grep '^[\/]\|^[a-zA-Z]:[/\]' | while read -r test; do \ + echo ''; \ + echo "Running test: $$test"; \ + NODE_ENV="$(NODE_ENV_TEST)" \ + NODE_PATH="$(NODE_PATH)" \ + $(JAVASCRIPT_TEST) \ + $(JAVASCRIPT_TEST_FLAGS) \ + $$test \ + | $(TAP_REPORTER) || exit 1; \ + done + +.PHONY: test + +#/ +# Runs unit tests and generate a test coverage report. +# +# @example +# make test-cov +#/ +test-cov: clean-cov + $(QUIET) NODE_ENV="$(NODE_ENV_TEST)" \ + NODE_PATH="$(NODE_PATH)" \ + $(ISTANBUL_COVER) $(ISTANBUL_COVER_FLAGS) $(JAVASCRIPT_TEST) -- $$( $(FIND_TESTS_CMD) ) + +.PHONY: test-cov + +#/ +# Removes a test coverage directory. +# +# @example +# make clean-cov +#/ +clean-cov: + $(QUIET) $(DELETE) $(DELETE_FLAGS) $(COVERAGE_DIR) diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..f5374f6 --- /dev/null +++ b/NOTICE @@ -0,0 +1 @@ +Copyright (c) 2016-2021 The Stdlib Authors. diff --git a/README.md b/README.md new file mode 100644 index 0000000..3be0a7c --- /dev/null +++ b/README.md @@ -0,0 +1,210 @@ + + +# prepend + +[![NPM version][npm-image]][npm-url] [![Build Status][test-image]][test-url] [![Coverage Status][coverage-image]][coverage-url] [![dependencies][dependencies-image]][dependencies-url] + +> Add elements from one collection to the beginning of another collection. + + + +
+ +
+ + + + + +
+ +## Installation + +```bash +npm install @stdlib/utils-prepend +``` + +
+ +
+ +## Usage + +```javascript +var prepend = require( '@stdlib/utils-prepend' ); +``` + +#### prepend( collection1, collection2 ) + +Adds elements from one `collection` to the beginning of another `collection`. A `collection` may be either an [`Array`][mdn-array], [`Typed Array`][mdn-typed-array], or an array-like [`Object`][mdn-object] (i.e., an [`Object`][mdn-object] having a valid writable `length` property). + +```javascript +var arr = [ 1.0, 2.0, 3.0, 4.0, 5.0 ]; + +var out = prepend( arr, [ 6.0, 7.0 ] ); +// returns [ 6.0, 7.0, 1.0, 2.0, 3.0, 4.0, 5.0 ] + +var bool = ( out === arr ); +// returns true +``` + +Note that the function returns the extended collection. For [typed arrays][mdn-typed-array], the returned value is a new [typed array][mdn-typed-array] view whose underlying [`ArrayBuffer`][mdn-arraybuffer] may **not** equal the underlying [`ArrayBuffer`][mdn-arraybuffer] for the input `collection`. + +```javascript +var ArrayBuffer = require( '@stdlib/array-buffer' ); +var Float64Array= require( '@stdlib/array-float64' ); + +var buf = new ArrayBuffer( 3*8 ); // 8 bytes per double + +var arr = new Float64Array( buf, 8, 2 ); +arr[ 0 ] = 1.0; +arr[ 1 ] = 2.0; + +var out = prepend( arr, [ 3.0 ] ); +// returns [ 3.0, 1.0, 2.0 ] + +var bool = ( out === arr ); +// returns false + +bool = ( out.buffer === arr.buffer ); +// returns true + +out = prepend( out, [ 4.0 ] ); +// returns [ 4.0, 3.0, 1.0, 2.0 ] + +bool = ( out.buffer === arr.buffer ); +// returns false +``` + +
+ + + + + +
+ +## Notes + +- The function adds elements to a [typed array][mdn-typed-array] by setting values in the underlying [`ArrayBuffer`][mdn-arraybuffer]. If an [`ArrayBuffer`][mdn-arraybuffer] does not have enough bytes in which to store all elements, the function allocates a new [`ArrayBuffer`][mdn-arraybuffer] capable of holding `2^n` elements, where `n` is the next power of `2`. This procedure is similar to how environments internally handle dynamic memory allocation for [`Arrays`][mdn-array]. +- Beware when providing [typed arrays][mdn-typed-array] which are views pointing to a shared (or pooled) [`ArrayBuffer`][mdn-arraybuffer]. Because the function sets [`ArrayBuffer`][mdn-arraybuffer] bytes outside of a provided [view][mdn-typed-array], the function may overwrite bytes belonging to one or more external views. This could be a potential **security vulnerability**. Prefer providing [typed arrays][mdn-typed-array] which have an exclusive [`ArrayBuffer`][mdn-arraybuffer]; otherwise, be sure to plan for and guard against mutated state. + +
+ + + + + +
+ +## Examples + + + +```javascript +var Float64Array= require( '@stdlib/array-float64' ); +var prepend = require( '@stdlib/utils-prepend' ); + +var arr; +var i; +var j; + +arr = new Float64Array(); +for ( i = 0; i < 100; i++ ) { + j = i * 3; + arr = prepend( arr, [ j+2, j+1, j ] ); +} +console.log( arr ); +``` + +
+ + + + + +
+ +
+ + + + + + +
+ +* * * + +## Notice + +This package is part of [stdlib][stdlib], a standard library for JavaScript and Node.js, with an emphasis on numerical and scientific computing. The library provides a collection of robust, high performance libraries for mathematics, statistics, streams, utilities, and more. + +For more information on the project, filing bug reports and feature requests, and guidance on how to develop [stdlib][stdlib], see the main project [repository][stdlib]. + +--- + +## License + +See [LICENSE][stdlib-license]. + + +## Copyright + +Copyright © 2016-2021. The Stdlib [Authors][stdlib-authors]. + +
+ + + + + + + + diff --git a/benchmark/benchmark.js b/benchmark/benchmark.js new file mode 100644 index 0000000..68bdf25 --- /dev/null +++ b/benchmark/benchmark.js @@ -0,0 +1,94 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var pkg = require( './../package.json' ).name; +var prepend = require( './../lib' ); + + +// MAIN // + +bench( pkg+'::array', function benchmark( b ) { + var arr; + var i; + + arr = []; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = prepend( arr, [ i, i+1, i+2 ] ); + if ( arr.length !== 3*(i+1) ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::built-in', function benchmark( b ) { + var arr; + var i; + + arr = []; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr.unshift( i, i+1, i+2 ); + if ( arr.length !== 3*(i+1) ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::built-in,apply', function benchmark( b ) { + var unshift; + var arr; + var i; + + unshift = Array.prototype.unshift; + + arr = []; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + unshift.apply( arr, [ i, i+1, i+2 ] ); + if ( arr.length !== 3*(i+1) ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/benchmark/benchmark.object.js b/benchmark/benchmark.object.js new file mode 100644 index 0000000..fa2f0fb --- /dev/null +++ b/benchmark/benchmark.object.js @@ -0,0 +1,77 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var pkg = require( './../package.json' ).name; +var prepend = require( './../lib' ); + + +// MAIN // + +bench( pkg+'::object', function benchmark( b ) { + var arr; + var i; + + arr = { + 'length': 0 + }; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = prepend( arr, [ i, i+1, i+2 ] ); + if ( arr.length !== 3*(i+1) ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::built-in,object', function benchmark( b ) { + var unshift; + var arr; + var i; + + unshift = Array.prototype.unshift; + + arr = { + 'length': 0 + }; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + unshift.apply( arr, [ i, i+1, i+2 ] ); + if ( arr.length !== 3*(i+1) ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/benchmark/benchmark.preallocation.js b/benchmark/benchmark.preallocation.js new file mode 100644 index 0000000..b5bebd1 --- /dev/null +++ b/benchmark/benchmark.preallocation.js @@ -0,0 +1,138 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var Float64Array = require( '@stdlib/array-float64' ); +var ArrayBuffer = require( '@stdlib/array-buffer' ); +var pkg = require( './../package.json' ).name; +var prepend = require( './../lib' ); + + +// MAIN // + +bench( pkg+'::float64array,preallocated', function benchmark( b ) { + var arr; + var buf; + var i; + + buf = new ArrayBuffer( b.iterations*8*3 ); // 8 bytes per double + arr = new Float64Array( buf, buf.byteLength, 0 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = prepend( arr, [ i, i+1, i+2 ] ); + if ( arr.length !== 3*(i+1) ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::float64array,preallocated,no-wrapper', function benchmark( b ) { + var prepend; + var arr; + var buf; + var i; + + prepend = require( './../lib/prepend_typed_array.js' ); + + buf = new ArrayBuffer( b.iterations*8*3 ); // 8 bytes per double + arr = new Float64Array( buf, b.iterations*8*3, 0 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = prepend( arr, [ i, i+1, i+2 ] ); + if ( arr.length !== 3*(i+1) ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::float64array,control,preallocated,constructor', function benchmark( b ) { + var offset; + var arr; + var buf; + var i; + var k; + + buf = new ArrayBuffer( b.iterations*8*3 ); // 8 bytes per double + arr = new Float64Array( buf, b.iterations*8*3, 0 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + // Here, we are only testing the operation of creating a new view each time a value must be added to a typed array: + k = 3 * (i+1); + offset = arr.byteOffset - ( arr.BYTES_PER_ELEMENT*3 ); + arr = new Float64Array( arr.buffer, offset, k ); + if ( arr.length !== k ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::float64array,control,preallocated,constructor,value', function benchmark( b ) { + var offset; + var arr; + var buf; + var i; + var j; + var k; + + buf = new ArrayBuffer( b.iterations*8*3 ); // 8 bytes per double + arr = new Float64Array( buf, b.iterations*8*3, 0 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + k = 3 * (i+1); + offset = arr.byteOffset - ( arr.BYTES_PER_ELEMENT*3 ); + arr = new Float64Array( arr.buffer, offset, k ); + for ( j = 0; j < 3; j++ ) { + arr[ j ] = i + j; + } + if ( arr.length !== k ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/benchmark/benchmark.typed_array.js b/benchmark/benchmark.typed_array.js new file mode 100644 index 0000000..4e2590b --- /dev/null +++ b/benchmark/benchmark.typed_array.js @@ -0,0 +1,246 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var MAX_INT32 = require( '@stdlib/constants-int32-max' ); +var MAX_UINT32 = require( '@stdlib/constants-uint32-max' ); +var MAX_INT16 = require( '@stdlib/constants-int16-max' ); +var MAX_UINT16 = require( '@stdlib/constants-uint16-max' ); +var MAX_INT8 = require( '@stdlib/constants-int8-max' ); +var MAX_UINT8 = require( '@stdlib/constants-uint8-max' ); +var Float32Array = require( '@stdlib/array-float32' ); +var Float64Array = require( '@stdlib/array-float64' ); +var Int8Array = require( '@stdlib/array-int8' ); +var Int16Array = require( '@stdlib/array-int16' ); +var Int32Array = require( '@stdlib/array-int32' ); +var Uint8Array = require( '@stdlib/array-uint8' ); +var Uint8ClampedArray = require( '@stdlib/array-uint8c' ); +var Uint16Array = require( '@stdlib/array-uint16' ); +var Uint32Array = require( '@stdlib/array-uint32' ); +var pkg = require( './../package.json' ).name; +var prepend = require( './../lib' ); + + +// MAIN // + +bench( pkg+'::float64array', function benchmark( b ) { + var arr; + var i; + + arr = new Float64Array(); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = prepend( arr, [ i, i+1, i+2 ] ); + if ( arr.length !== 3*(i+1) ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::float32array', function benchmark( b ) { + var arr; + var i; + + arr = new Float32Array(); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = prepend( arr, [ i, i+1, i+2 ] ); + if ( arr.length !== 3*(i+1) ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::int32array', function benchmark( b ) { + var arr; + var max; + var i; + + max = MAX_INT32 + 1; + arr = new Int32Array(); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = prepend( arr, [ i%max, (i+1)%max, (i+2)%max ] ); + if ( arr.length !== 3*(i+1) ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::uint32array', function benchmark( b ) { + var arr; + var max; + var i; + + max = MAX_UINT32 + 1; + arr = new Uint32Array(); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = prepend( arr, [ i%max, (i+1)%max, (i+2)%max ] ); + if ( arr.length !== 3*(i+1) ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::int16array', function benchmark( b ) { + var arr; + var max; + var i; + + max = MAX_INT16 + 1; + arr = new Int16Array(); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = prepend( arr, [ i%max, (i+1)%max, (i+2)%max ] ); + if ( arr.length !== 3*(i+1) ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::uint16array', function benchmark( b ) { + var arr; + var max; + var i; + + max = MAX_UINT16 + 1; + arr = new Uint16Array(); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = prepend( arr, [ i%max, (i+1)%max, (i+2)%max ] ); + if ( arr.length !== 3*(i+1) ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::int8array', function benchmark( b ) { + var arr; + var max; + var i; + + max = MAX_INT8 + 1; + arr = new Int8Array(); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = prepend( arr, [ i%max, (i+1)%max, (i+2)%max ] ); + if ( arr.length !== 3*(i+1) ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::uint8array', function benchmark( b ) { + var arr; + var max; + var i; + + max = MAX_UINT8 + 1; + arr = new Uint8Array(); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = prepend( arr, [ i%max, (i+1)%max, (i+2)%max ] ); + if ( arr.length !== 3*(i+1) ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::uint8clampedarray', function benchmark( b ) { + var arr; + var max; + var i; + + max = MAX_UINT8 + 1; + arr = new Uint8ClampedArray(); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = prepend( arr, [ i%max, (i+1)%max, (i+2)%max ] ); + if ( arr.length !== 3*(i+1) ) { + b.fail( 'should have added an element' ); + } + } + b.toc(); + if ( arr.length !== b.iterations*3 ) { + b.fail( 'should have added elements' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/docs/repl.txt b/docs/repl.txt new file mode 100644 index 0000000..f308559 --- /dev/null +++ b/docs/repl.txt @@ -0,0 +1,46 @@ + +{{alias}}( collection1, collection2 ) + Adds the elements of one collection to the beginning of another collection. + + If the input collection is a typed array, the output value does not equal + the input reference and the underlying `ArrayBuffer` may *not* be the same + as the `ArrayBuffer` belonging to the input view. + + For purposes of generality, always treat the output collection as distinct + from the input collection. + + Parameters + ---------- + collection1: Array|TypedArray|Object + A collection. If the collection is an `Object`, the collection should be + array-like. + + collection2: Array|TypedArray|Object + A collection containing the elements to add. If the collection is an + `Object`, the collection should be array-like. + + Returns + ------- + out: Array|TypedArray|Object + Updated collection. + + Examples + -------- + // Arrays: + > var arr = [ 1.0, 2.0, 3.0, 4.0, 5.0 ]; + > arr = {{alias}}( arr, [ 6.0, 7.0 ] ) + [ 6.0, 7.0, 1.0, 2.0, 3.0, 4.0, 5.0 ] + + // Typed arrays: + > arr = new {{alias:@stdlib/array/float64}}( [ 1.0, 2.0 ] ); + > arr = {{alias}}( arr, [ 3.0, 4.0 ] ) + [ 3.0, 4.0, 1.0, 2.0 ] + + // Array-like object: + > arr = { 'length': 1, '0': 1.0 }; + > arr = {{alias}}( arr, [ 2.0, 3.0 ] ) + { 'length': 3, '0': 2.0, '1': 3.0, '2': 1.0 } + + See Also + -------- + diff --git a/docs/types/index.d.ts b/docs/types/index.d.ts new file mode 100644 index 0000000..5a01fb3 --- /dev/null +++ b/docs/types/index.d.ts @@ -0,0 +1,57 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2019 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// TypeScript Version: 2.0 + +/// + +import { Collection } from '@stdlib/types/object'; + +/** +* Adds elements from one collection to the beginning of another collection. +* +* ## Notes +* +* - If the input collection is a typed array, the output value does not equal the input reference and the underlying `ArrayBuffer` may *not* be the same as the `ArrayBuffer` belonging to the input view. +* - For purposes of generality, always treat the output collection as distinct from the input collection. +* +* @param collection1 - collection +* @param collection2 - collection containing elements to add +* @returns updated collection +* +* @example +* var arr = [ 1.0, 2.0, 3.0, 4.0, 5.0 ]; +* +* arr = prepend( arr, [ 6.0, 7.0 ] ); +* // returns [ 6.0, 7.0, 1.0, 2.0, 3.0, 4.0, 5.0 ] +* +* @example +* var Float64Array = require( `@stdlib/array/float64` ); +* +* var arr = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0 ] ); +* // returns [ 1.0, 2.0, 3.0, 4.0, 5.0 ] +* +* arr = prepend( arr, [ 6.0, 7.0 ] ); +* // returns [ 6.0, 7.0, 1.0, 2.0, 3.0, 4.0, 5.0 ] +*/ +declare function prepend( collection1: Collection, collection2: Collection ): Collection; // tslint-disable-line max-line-length + + +// EXPORTS // + +export = prepend; diff --git a/docs/types/test.ts b/docs/types/test.ts new file mode 100644 index 0000000..6f794b9 --- /dev/null +++ b/docs/types/test.ts @@ -0,0 +1,51 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2019 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import prepend = require( './index' ); + + +// TESTS // + +// The function returns a collection... +{ + prepend( [ 0, 0 ], [ 1, 1 ] ); // $ExpectType Collection + prepend( [ false, true ], [ 0, 1 ] ); // $ExpectType Collection + prepend( [ 'abc', 'abc' ], [ 0, 1 ] ); // $ExpectType Collection + prepend( [ true, true ], [ false, false ] ); // $ExpectType Collection +} + +// The compiler throws an error if the function is provided a first argument which is not a collection... +{ + prepend( true, [] ); // $ExpectError + prepend( false, [] ); // $ExpectError + prepend( 5, [] ); // $ExpectError +} + +// The compiler throws an error if the function is provided a second argument which is not a collection... +{ + prepend( [], true ); // $ExpectError + prepend( [], false ); // $ExpectError + prepend( [], 5 ); // $ExpectError +} + +// The compiler throws an error if the function is not provided two arguments... +{ + prepend(); // $ExpectError + prepend( [ true, true ] ); // $ExpectError + prepend( [ true, true ], [ true, false ], 3 ); // $ExpectError +} diff --git a/examples/index.js b/examples/index.js new file mode 100644 index 0000000..835c157 --- /dev/null +++ b/examples/index.js @@ -0,0 +1,35 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var Float64Array = require( '@stdlib/array-float64' ); +var prepend = require( './../lib' ); + +var arr; +var i; +var j; + +arr = new Float64Array(); +for ( i = 0; i < 100; i++ ) { + j = i * 3; + arr = prepend( arr, [ j+2, j+1, j ] ); +} +console.log( arr ); +console.log( 'View Length: %d', arr.byteLength ); +console.log( 'Buffer Length: %d', arr.buffer.byteLength ); diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..bc569c7 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,49 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Add the elements of one collection to the beginning of another collection. +* +* @module @stdlib/utils/prepend +* +* @example +* var prepend = require( '@stdlib/utils-prepend' ); +* var Float64Array = require( '@stdlib/array-float64' ); +* +* var arr = [ 1.0, 2.0, 3.0, 4.0, 5.0 ]; +* +* arr = prepend( arr, [ 6.0, 7.0 ] ); +* // returns [ 6.0, 7.0, 1.0, 2.0, 3.0, 4.0, 5.0 ] +* +* arr = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0 ] ); +* // returns [ 1.0, 2.0, 3.0, 4.0, 5.0 ] +* +* arr = prepend( arr, [ 6.0, 7.0 ] ); +* // returns [ 6.0, 7.0, 1.0, 2.0, 3.0, 4.0, 5.0 ] +*/ + +// MODULES // + +var prepend = require( './prepend.js' ); + + +// EXPORTS // + +module.exports = prepend; diff --git a/lib/prepend.js b/lib/prepend.js new file mode 100644 index 0000000..2dc5446 --- /dev/null +++ b/lib/prepend.js @@ -0,0 +1,85 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var isArray = require( '@stdlib/assert-is-array' ); +var isCollection = require( '@stdlib/assert-is-collection' ); +var isTypedArrayLike = require( '@stdlib/assert-is-typed-array-like' ); +var isInteger = require( '@stdlib/assert-is-integer' ); +var prependArray = require( './prepend_array.js' ); +var prependObject = require( './prepend_object.js' ); +var prependTypedArray = require( './prepend_typed_array.js' ); + + +// MAIN // + +/** +* Adds elements from one collection to the beginning of another collection. +* +* @param {Collection} collection1 - collection +* @param {Collection} collection2 - collection containing elements to add +* @throws {TypeError} first argument must be either an array, typed array, or an array-like object +* @throws {TypeError} second argument must be an array-like object +* @returns {Collection} updated collection +* +* @example +* var arr = [ 1.0, 2.0, 3.0, 4.0, 5.0 ]; +* +* arr = prepend( arr, [ 6.0, 7.0 ] ); +* // returns [ 6.0, 7.0, 1.0, 2.0, 3.0, 4.0, 5.0 ] +* +* @example +* var Float64Array = require( '@stdlib/array-float64' ); +* +* var arr = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0 ] ); +* // returns [ 1.0, 2.0, 3.0, 4.0, 5.0 ] +* +* arr = prepend( arr, [ 6.0, 7.0 ] ); +* // returns [ 6.0, 7.0, 1.0, 2.0, 3.0, 4.0, 5.0 ] +*/ +function prepend( collection1, collection2 ) { + if ( !isCollection( collection2 ) ) { + throw new TypeError( 'invalid argument. Second argument must be an array-like object. Value: `'+collection2+'`.' ); + } + if ( isArray( collection1 ) ) { + return prependArray( collection1, collection2 ); + } + // Check for a typed-array-like object, as verifying actual typed arrays is expensive... + if ( isTypedArrayLike( collection1 ) ) { + return prependTypedArray( collection1, collection2 ); + } + // Check for an array-like object... + if ( + collection1 !== null && + typeof collection1 === 'object' && + typeof collection1.length === 'number' && + isInteger( collection1.length ) && + collection1.length >= 0 + ) { + return prependObject( collection1, collection2 ); + } + throw new TypeError( 'invalid argument. First argument must be either an Array, Typed Array, or an array-like Object. Value: `'+collection1+'`.' ); +} + + +// EXPORTS // + +module.exports = prepend; diff --git a/lib/prepend_array.js b/lib/prepend_array.js new file mode 100644 index 0000000..b65fc6f --- /dev/null +++ b/lib/prepend_array.js @@ -0,0 +1,48 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MAIN // + +/** +* Adds elements from a collection to the beginning of an array. +* +* @private +* @param {Array} arr - input array +* @param {ArrayLike} items - items to add +* @returns {Array} input array +* +* @example +* var arr = [ 1.0, 2.0, 3.0, 4.0, 5.0 ]; +* +* arr = prepend( arr, [ 6.0, 7.0 ] ); +* // returns [ 6.0, 7.0, 1.0, 2.0, 3.0, 4.0, 5.0 ] +*/ +function prepend( arr, items ) { + var i; + for ( i = items.length-1; i >= 0; i-- ) { + arr.unshift( items[ i ] ); + } + return arr; +} + + +// EXPORTS // + +module.exports = prepend; diff --git a/lib/prepend_object.js b/lib/prepend_object.js new file mode 100644 index 0000000..950c490 --- /dev/null +++ b/lib/prepend_object.js @@ -0,0 +1,64 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MAIN // + +/** +* Adds elements from a collection to the beginning of an array-like object. +* +* @private +* @param {Object} obj - input array-like object +* @param {ArrayLike} items - items to add +* @returns {Object} input object +* +* @example +* var obj = { +* 'length': 2, +* '0': 1.0, +* '1': 2.0 +* }; +* +* obj = prepend( obj, [ 3.0, 4.0 ] ); +* // returns { 'length': 4, '0': 3.0, '1': 4.0, '2': 1.0, '3': 2.0 } +*/ +function prepend( obj, items ) { + var len; + var n; + var i; + + len = obj.length; + n = items.length; + + // Shift all existing elements to the right... + for ( i = len-1; i >= 0; i-- ) { + obj[ i+n ] = obj[ i ]; + } + // Add new elements... + for ( i = 0; i < n; i++ ) { + obj[ i ] = items[ i ]; + } + obj.length = len + n; + return obj; +} + + +// EXPORTS // + +module.exports = prepend; diff --git a/lib/prepend_typed_array.js b/lib/prepend_typed_array.js new file mode 100644 index 0000000..b896d5e --- /dev/null +++ b/lib/prepend_typed_array.js @@ -0,0 +1,90 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var ArrayBuffer = require( '@stdlib/array-buffer' ); +var ceil2 = require( '@stdlib/math-base-special-ceil2' ); -- TODO: nextpow2 + + +// MAIN // + +/** +* Adds elements from a collection to the beginning of a typed array. +* +* ## Notes +* +* - If the underlying `ArrayBuffer` is too short, we need to copy the data to a new `ArrayBuffer`. To do so, we allocate a new `ArrayBuffer` in a manner similar to how `Arrays` are resized (i.e., allocate enough memory to hold `nextpow2(n)` elements). +* - Beware that, if an ArrayBuffer view is preceded by one or more other views, the created view may contain elements from those views, thus resulting in possible mutation. Accordingly, providing a typed array view having a shared underlying `ArrayBuffer` may have unintended consequences (including security vulnerabilities). +* +* @private +* @param {TypedArray} arr - input array +* @param {ArrayLike} items - items to add +* @returns {TypedArray} input array +* +* @example +* var Float64Array = require( '@stdlib/array-float64' ); +* +* var arr = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0 ] ); +* // returns [ 1.0, 2.0, 3.0, 4.0, 5.0 ] +* +* arr = prepend( arr, [ 6.0, 7.0 ] ); +* // returns [ 6.0, 7.0, 1.0, 2.0, 3.0, 4.0, 5.0 ] +*/ +function prepend( arr, items ) { + var nbytes; + var ibytes; + var offset; + var total; + var len; + var buf; + var n; + var v; + var i; + + len = arr.length; + n = items.length; + + ibytes = n * arr.BYTES_PER_ELEMENT; + offset = arr.byteOffset; + + if ( offset < ibytes ) { + nbytes = len * arr.BYTES_PER_ELEMENT; + total = nbytes + ibytes + offset; + buf = new ArrayBuffer( ceil2( total+1 ) ); + offset = buf.byteLength - nbytes - ibytes; + v = new arr.constructor( buf, offset, len+n ); + for ( i = 0; i < len; i++ ) { + v[ i+n ] = arr[ i ]; + } + } else { + offset -= ibytes; + v = new arr.constructor( arr.buffer, offset, len+n ); + } + for ( i = 0; i < n; i++ ) { + v[ i ] = items[ i ]; + } + return v; +} + + +// EXPORTS // + +module.exports = prepend; diff --git a/package.json b/package.json new file mode 100644 index 0000000..19e03db --- /dev/null +++ b/package.json @@ -0,0 +1,117 @@ +{ + "name": "@stdlib/utils-prepend", + "version": "0.0.0", + "description": "Add elements from one collection to the beginning of another collection.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "main": "./lib", + "directories": { + "benchmark": "./benchmark", + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "types": "./docs/types", + "scripts": { + "test": "make test", + "test-cov": "make test-cov", + "examples": "make examples", + "benchmark": "make benchmark" + }, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/utils-prepend.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": { + "@stdlib/array-buffer": "^0.0.x", + "@stdlib/assert-is-array": "^0.0.x", + "@stdlib/assert-is-collection": "^0.0.x", + "@stdlib/assert-is-integer": "^0.0.x", + "@stdlib/assert-is-typed-array-like": "^0.0.x", + "@stdlib/math-base-special-ceil2": "^0.0.x", + "@stdlib/types": "^0.0.x" + }, + "devDependencies": { + "@stdlib/array-float32": "^0.0.x", + "@stdlib/array-float64": "^0.0.x", + "@stdlib/array-int16": "^0.0.x", + "@stdlib/array-int32": "^0.0.x", + "@stdlib/array-int8": "^0.0.x", + "@stdlib/array-uint16": "^0.0.x", + "@stdlib/array-uint32": "^0.0.x", + "@stdlib/array-uint8": "^0.0.x", + "@stdlib/array-uint8c": "^0.0.x", + "@stdlib/bench": "^0.0.x", + "@stdlib/constants-int16-max": "^0.0.x", + "@stdlib/constants-int32-max": "^0.0.x", + "@stdlib/constants-int8-max": "^0.0.x", + "@stdlib/constants-uint16-max": "^0.0.x", + "@stdlib/constants-uint32-max": "^0.0.x", + "@stdlib/constants-uint8-max": "^0.0.x", + "tape": "git+https://github.com/kgryte/tape.git#fix/globby", + "istanbul": "^0.4.1", + "tap-spec": "5.x.x" + }, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "stdutils", + "stdutil", + "utilities", + "utility", + "utils", + "util", + "unshift", + "prepend", + "append", + "extend", + "lengthen", + "array", + "typed array", + "typed-array", + "float64array", + "float32array", + "int32array", + "uint32array", + "int16array", + "uint16array", + "int8array", + "uint8array", + "uint8clampedarray", + "array-like", + "object", + "obj" + ], + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/athan" + } +} diff --git a/test/test.js b/test/test.js new file mode 100644 index 0000000..c198cf7 --- /dev/null +++ b/test/test.js @@ -0,0 +1,357 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2018 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/* eslint-disable object-curly-newline */ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var Float64Array = require( '@stdlib/array-float64' ); +var ArrayBuffer = require( '@stdlib/array-buffer' ); +var prepend = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof prepend, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function throws an error if not provided either an array, typed array, or an array-like object', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + NaN, + true, + false, + null, + undefined, + function noop() {}, + new Date(), + new RegExp( '.+' ), + {}, + { 'length': null }, + { 'length': -1 }, + { 'length': 3.14 } + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), TypeError, 'throws a type error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + prepend( value, [ 1.0 ] ); + }; + } +}); + +tape( 'the function throws an error if not provided an array-like object', function test( t ) { + var values; + var i; + + values = [ + // '5', // this is considered array-like + 5, + NaN, + true, + false, + null, + undefined, + function noop() {}, + new Date(), + new RegExp( '.+' ), + {}, + { 'length': null }, + { 'length': -1 }, + { 'length': 3.14 } + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), TypeError, 'throws a type error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + prepend( [ 1.0, 2.0 ], value ); + }; + } +}); + +tape( 'the function adds the elements of a collection to an array', function test( t ) { + var expected; + var arr; + var out; + + arr = [ 1.0, 2.0, 3.0, 4.0, 5.0 ]; + out = prepend( arr, [ 6.0 ] ); + + t.strictEqual( out, arr, 'returns input array' ); + + expected = [ 6.0, 1.0, 2.0, 3.0, 4.0, 5.0 ]; + t.deepEqual( arr, expected, 'deep equal' ); + + out = prepend( arr, [ 7.0, 8.0 ] ); + + expected = [ 7.0, 8.0, 6.0, 1.0, 2.0, 3.0, 4.0, 5.0 ]; + t.deepEqual( arr, expected, 'deep equal' ); + + t.end(); +}); + +tape( 'the function adds the elements of a collection to an array-like object', function test( t ) { + var expected; + var arr; + var out; + + arr = { + 'length': 0 + }; + out = prepend( arr, [ 1.0 ] ); + + t.strictEqual( out, arr, 'returns input collection' ); + + expected = { + 'length': 1, + '0': 1.0 + }; + t.deepEqual( arr, expected, 'deep equal' ); + + out = prepend( arr, [ 2.0, 3.0 ] ); + + expected = { + 'length': 3, + '0': 2.0, + '1': 3.0, + '2': 1.0 + }; + t.deepEqual( arr, expected, 'deep equal' ); + + t.end(); +}); + +tape( 'the function adds elements from a collection to a typed array', function test( t ) { + var expected; + var arr; + var out; + var i; + + arr = new Float64Array(); + out = prepend( arr, [ 1.0 ] ); + + t.notEqual( out, arr, 'does not return input array (new view)' ); + + expected = new Float64Array( [ 1.0 ] ); + for ( i = 0; i < expected.length; i++ ) { + t.strictEqual( out[ i ], expected[ i ], 'has expected value for element '+i ); + } + + out = prepend( out, [ 2.0, 3.0, 4.0 ] ); + + expected = new Float64Array( [ 2.0, 3.0, 4.0, 1.0 ] ); + for ( i = 0; i < expected.length; i++ ) { + t.strictEqual( out[ i ], expected[ i ], 'has expected value for element '+i ); + } + // eslint-disable-next-line max-len + out = prepend( out, [ 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0 ] ); + + expected = new Float64Array([ + 5.0, + 6.0, + 7.0, + 8.0, + 9.0, + 10.0, + 11.0, + 12.0, + 13.0, + 14.0, + 2.0, + 3.0, + 4.0, + 1.0 + ]); + for ( i = 0; i < expected.length; i++ ) { + t.strictEqual( out[ i ], expected[ i ], 'has expected value for element '+i ); + } + + t.end(); +}); + +tape( 'the function adds elements from a collection to a typed array (preallocated buffer)', function test( t ) { + var expected; + var buf; + var arr; + var out; + var i; + + buf = new ArrayBuffer( 64000 ); + arr = new Float64Array( buf, buf.byteLength, 0 ); + out = prepend( arr, [ 1.0 ] ); + + t.notEqual( out, arr, 'does not return input array (new view)' ); + + expected = new Float64Array( [ 1.0 ] ); + for ( i = 0; i < expected.length; i++ ) { + t.strictEqual( out[ i ], expected[ i ], 'has expected value for element '+i ); + } + t.strictEqual( out.buffer, arr.buffer, 'same underlying buffer' ); + + out = prepend( out, [ 2.0, 3.0, 4.0 ] ); + + expected = new Float64Array( [ 2.0, 3.0, 4.0, 1.0 ] ); + for ( i = 0; i < expected.length; i++ ) { + t.strictEqual( out[ i ], expected[ i ], 'has expected value for element '+i ); + } + t.strictEqual( out.buffer, arr.buffer, 'same underlying buffer' ); + + // eslint-disable-next-line max-len + out = prepend( out, [ 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0 ] ); + + expected = new Float64Array([ + 5.0, + 6.0, + 7.0, + 8.0, + 9.0, + 10.0, + 11.0, + 12.0, + 13.0, + 14.0, + 2.0, + 3.0, + 4.0, + 1.0 + ]); + for ( i = 0; i < expected.length; i++ ) { + t.strictEqual( out[ i ], expected[ i ], 'has expected value for element '+i ); + } + t.strictEqual( out.buffer, arr.buffer, 'same underlying buffer' ); + + t.end(); +}); + +tape( 'the function adds one or more elements to a typed array (offset view)', function test( t ) { + var expected; + var arr; + var buf; + var out; + var i; + + buf = new ArrayBuffer( 32 ); + arr = new Float64Array( buf, 3*8, 0 ); // 8 bytes per double + out = prepend( arr, [ 1.0 ] ); + + t.notEqual( out, arr, 'does not return input array (new view)' ); + + expected = new Float64Array( [ 1.0 ] ); + for ( i = 0; i < expected.length; i++ ) { + t.strictEqual( out[ i ], expected[ i ], 'has expected value for element '+i ); + } + t.strictEqual( out.buffer, arr.buffer, 'same underlying buffer' ); + + out = prepend( out, [ 2.0, 3.0, 4.0 ] ); + + expected = new Float64Array( [ 2.0, 3.0, 4.0, 1.0 ] ); + for ( i = 0; i < expected.length; i++ ) { + t.strictEqual( out[ i ], expected[ i ], 'has expected value for element '+i ); + } + t.notEqual( out.buffer, arr.buffer, 'new underlying buffer' ); + + // eslint-disable-next-line max-len + out = prepend( out, [ 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0 ] ); + + expected = new Float64Array([ + 5.0, + 6.0, + 7.0, + 8.0, + 9.0, + 10.0, + 11.0, + 12.0, + 13.0, + 14.0, + 2.0, + 3.0, + 4.0, + 1.0 + ]); + for ( i = 0; i < expected.length; i++ ) { + t.strictEqual( out[ i ], expected[ i ], 'has expected value for element '+i ); + } + t.notEqual( out.buffer, arr.buffer, 'new underlying buffer' ); + + t.end(); +}); + +tape( 'the function adds elements from a collection to a typed array (shared `ArrayBuffer`)', function test( t ) { + var expected; + var arr1; + var arr2; + var arr3; + var buf; + var out; + var i; + + buf = new ArrayBuffer( 64 ); + + arr1 = new Float64Array( buf, 2*8, 2 ); // 8 bytes per double + arr2 = new Float64Array( buf, 4*8, 2 ); + arr3 = new Float64Array( buf, 6*8, 0 ); + + arr1[ 0 ] = 3.14; + arr1[ 1 ] = 6.28; + + arr2[ 0 ] = -3.14; + arr2[ 1 ] = -6.28; + + out = prepend( arr3, [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] ); + + t.notEqual( out, arr3, 'does not return input array (new view)' ); + + expected = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] ); + for ( i = 0; i < expected.length; i++ ) { + t.strictEqual( out[ i ], expected[ i ], 'has expected value for element '+i ); + } + t.strictEqual( out.buffer, arr3.buffer, 'same underlying buffer' ); + + expected = new Float64Array( [ 5.0, 6.0 ] ); + for ( i = 0; i < expected.length; i++ ) { + t.strictEqual( arr2[ i ], expected[ i ], 'value was overwritten for element '+i ); + } + t.strictEqual( out.buffer, arr2.buffer, 'same underlying buffer' ); + + expected = new Float64Array( [ 3.0, 4.0 ] ); + for ( i = 0; i < expected.length; i++ ) { + t.strictEqual( arr1[ i ], expected[ i ], 'value was overwritten for element '+i ); + } + t.strictEqual( out.buffer, arr1.buffer, 'same underlying buffer' ); + + t.end(); +});