├── .babelrc ├── .eslintrc.yml ├── .gitignore ├── .gitmodules ├── .travis.yml ├── History.md ├── LICENSE ├── Makefile ├── README.md ├── docs ├── assets │ ├── anchor.js │ ├── bass-addons.css │ ├── bass.css │ ├── fonts │ │ ├── EOT │ │ │ ├── SourceCodePro-Bold.eot │ │ │ └── SourceCodePro-Regular.eot │ │ ├── LICENSE.txt │ │ ├── OTF │ │ │ ├── SourceCodePro-Bold.otf │ │ │ └── SourceCodePro-Regular.otf │ │ ├── TTF │ │ │ ├── SourceCodePro-Bold.ttf │ │ │ └── SourceCodePro-Regular.ttf │ │ ├── WOFF │ │ │ ├── OTF │ │ │ │ ├── SourceCodePro-Bold.otf.woff │ │ │ │ └── SourceCodePro-Regular.otf.woff │ │ │ └── TTF │ │ │ │ ├── SourceCodePro-Bold.ttf.woff │ │ │ │ └── SourceCodePro-Regular.ttf.woff │ │ ├── WOFF2 │ │ │ ├── OTF │ │ │ │ ├── SourceCodePro-Bold.otf.woff2 │ │ │ │ └── SourceCodePro-Regular.otf.woff2 │ │ │ └── TTF │ │ │ │ ├── SourceCodePro-Bold.ttf.woff2 │ │ │ │ └── SourceCodePro-Regular.ttf.woff2 │ │ └── source-code-pro.css │ ├── github.css │ ├── site.js │ ├── split.css │ ├── split.js │ └── style.css └── index.html ├── js-interfaces.cpp ├── js-interfaces.h ├── make └── minimum.mk ├── models ├── generate_model.py └── output.model ├── package-lock.json ├── package.json ├── replace-files ├── dmlc-core │ └── base.h ├── rabit │ └── base.h └── xgboost │ └── c_api.h ├── rollup.config.js └── src ├── __tests__ └── test.js ├── index.js ├── loadXGBoost.js └── wasmPreJS.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["transform-es2015-modules-commonjs"] 3 | } 4 | -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | extends: 'eslint-config-cheminfo' 2 | parserOptions: 3 | sourceType: module 4 | env: 5 | jest: true 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | lib 40 | dist 41 | .idea 42 | .vscode 43 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "xgboost"] 2 | path = xgboost 3 | url = https://github.com/dmlc/xgboost.git 4 | ignore = dirty 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | notifications: 2 | email: false 3 | 4 | language: node_js 5 | node_js: 6 | - 9 7 | - 8 8 | 9 | sudo: required 10 | 11 | services: 12 | - docker 13 | 14 | before_install: 15 | - docker run -dit --name emscripten -v $(pwd):/src trzeci/emscripten:sdk-tag-1.37.22-64bit bash 16 | 17 | script: 18 | - docker exec -it emscripten make 19 | - npm run test 20 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 2 | ## [1.1.2](https://github.com/mljs/xgboost/compare/v1.1.1...v1.1.2) (2018-02-19) 3 | 4 | 5 | ### Bug Fixes 6 | 7 | * change import to require because rollup doesn't transpile it well ([baaae20](https://github.com/mljs/xgboost/commit/baaae20)) 8 | 9 | 10 | 11 | 12 | ## [1.1.1](https://github.com/mljs/xgboost/compare/v1.1.0...v1.1.1) (2018-02-19) 13 | 14 | 15 | ### Bug Fixes 16 | 17 | * npm build now contains the xgboost.wasm for lib folder ([e93a2c5](https://github.com/mljs/xgboost/commit/e93a2c5)) 18 | 19 | 20 | 21 | 22 | # 1.1.0 (2018-02-19) 23 | 24 | 25 | ### Features 26 | 27 | * **loadFromModel:** Method working with tests ([79319c7](https://github.com/mljs/xgboost/commit/79319c7)) 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 by Contributors 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = emcc 2 | CXX = em++ 3 | 4 | ifndef RABIT 5 | RABIT = xgboost/rabit 6 | endif 7 | 8 | ifndef DMLC_CORE 9 | DMLC_CORE = xgboost/dmlc-core 10 | endif 11 | 12 | CFLAGS = -O3 -Wall -fPIC --memory-init-file 0 -std=c++11 13 | CFLAGS += -I$(DMLC_CORE)/include -I$(RABIT)/include -Ixgboost/include 14 | BUILD_DIR=dist 15 | EXPORTED_FUNCTIONS="['_create_model', '_set_param', '_train_full_model', '_predict_one', '_free_memory_model', '_save_model', '_get_file_content', '_load_model', '_prediction_size']" 16 | 17 | UNAME=$(shell uname) 18 | ifeq ($(UNAME), Darwin) 19 | COMPILED_FILES = xgboost/lib/libxgboost.dylib 20 | else 21 | COMPILED_FILES = xgboost/lib/libxgboost.so 22 | endif 23 | 24 | all: replace build 25 | 26 | replace: 27 | cp replace-files/dmlc-core/base.h ./xgboost/dmlc-core/include/dmlc/base.h; 28 | cp replace-files/rabit/base.h ./xgboost/rabit/include/dmlc/base.h; 29 | cp replace-files/xgboost/c_api.h ./xgboost/include/xgboost/c_api.h; 30 | 31 | build: 32 | cd xgboost; make -j4 config=../make/minimum.mk; cd ..; 33 | mkdir -p $(BUILD_DIR)/wasm; 34 | $(CXX) $(CFLAGS) js-interfaces.cpp $(COMPILED_FILES) -o $(BUILD_DIR)/wasm/xgboost.js --pre-js src/wasmPreJS.js -s WASM=1 -s "BINARYEN_METHOD='native-wasm'" -s ALLOW_MEMORY_GROWTH=1 -s EXPORTED_FUNCTIONS=$(EXPORTED_FUNCTIONS) 35 | # mkdir -p $(BUILD_DIR)/asm; 36 | # $(CXX) $(CFLAGS) js-interfaces.cpp $(COMPILED_FILES) -o $(BUILD_DIR)/asm/xgboost.js --pre-js src/asmPreJS.js -s EXPORTED_FUNCTIONS=$(EXPORTED_FUNCTIONS) #-s ALLOW_MEMORY_GROWTH=1 37 | 38 | clean: 39 | cd xgboost; make clean_all; cd ..; rm -rf dist; 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xgboost 2 | 3 | [![NPM version][npm-image]][npm-url] 4 | [![build status][travis-image]][travis-url] 5 | [![David deps][david-image]][david-url] 6 | [![npm download][download-image]][download-url] 7 | 8 | 9 | 10 | ## Installation 11 | 12 | `$ npm install ml-xgboost` 13 | 14 | ## [API Documentation](https://mljs.github.io/xgboost/) 15 | 16 | ## Example 17 | 18 | ```js 19 | import IrisDataset from 'ml-dataset-iris'; 20 | 21 | require('ml-xgboost').then(XGBoost => { 22 | var booster = new XGBoost({ 23 | booster: 'gbtree', 24 | objective: 'multi:softmax', 25 | max_depth: 5, 26 | eta: 0.1, 27 | min_child_weight: 1, 28 | subsample: 0.5, 29 | colsample_bytree: 1, 30 | silent: 1, 31 | iterations: 200 32 | }); 33 | 34 | var trainingSet = IrisDataset.getNumbers(); 35 | var predictions = IrisDataset.getClasses().map( 36 | (elem) => IrisDataset.getDistinctClasses().indexOf(elem) 37 | ); 38 | 39 | booster.train(dataset, trueLabels); 40 | var predictDataset = /* something to predict */ 41 | var predictions = booster.predict(predictDataset); 42 | 43 | // don't forget to free your model 44 | booster.free() 45 | 46 | // you can save your model in this way 47 | var model = JSON.stringify(booster); // string 48 | // or 49 | var model = booster.toJSON(); // object 50 | 51 | // and load it 52 | var anotherBooster = XGBoost.load(model); // model is an object, not a string 53 | }); 54 | ``` 55 | 56 | ## Development 57 | 58 | * You should have [emscripten sdk-1.37.22](http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html) installed on your computer and be able to use `emcc` and `em++`. 59 | * Download the repo: `git clone --recursive https://github.com/mljs/xgboost` 60 | * Run `npm run build` or `make` at the root directory. 61 | 62 | ## XGBoost library files changed 63 | 64 | * dmlc-core/include/dmlc/base.h line 45 [here](./xgboost/dmlc-core/include/dmlc/base.h) 65 | * rabit/include/dmlc/base.h line 45 [here](./xgboost/rabit/include/dmlc/base.h) 66 | 67 | ```C++ 68 | #if (!defined(DMLC_LOG_STACK_TRACE) && defined(__GNUC__) && !defined(__MINGW32__)) 69 | #define DMLC_LOG_STACK_TRACE 1 70 | #undef DMLC_LOG_STACK_TRACE 71 | #endif 72 | ``` 73 | **Note**: this is to avoid compilation issues with the execinfo.h library that is not needed in the JS library 74 | * in case that you get the following error: 75 | 76 | `./xgboost/include/xgboost/c_api.h:29:9: error: unknown type name 'uint64_t'` 77 | 78 | just add this import at the beginning of [this](./xgboost/include/xgboost/c_api.h) file after the first `define`: 79 | 80 | ```C++ 81 | #include 82 | ``` 83 | 84 | ## License 85 | 86 | © Contributors, 2016. Licensed under an [Apache-2](./LICENSE) license. 87 | 88 | [npm-image]: https://img.shields.io/npm/v/ml-xgboost.svg?style=flat-square 89 | [npm-url]: https://www.npmjs.com/package/ml-xgboost 90 | [travis-image]: https://img.shields.io/travis/mljs/xgboost/master.svg?style=flat-square 91 | [travis-url]: https://travis-ci.org/mljs/xgboost 92 | [david-image]: https://img.shields.io/david/mljs/xgboost.svg?style=flat-square 93 | [david-url]: https://david-dm.org/mljs/xgboost 94 | [download-image]: https://img.shields.io/npm/dm/ml-xgboost.svg?style=flat-square 95 | [download-url]: https://www.npmjs.com/package/ml-xgboost 96 | -------------------------------------------------------------------------------- /docs/assets/anchor.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * AnchorJS - v4.0.0 - 2017-06-02 3 | * https://github.com/bryanbraun/anchorjs 4 | * Copyright (c) 2017 Bryan Braun; Licensed MIT 5 | */ 6 | /* eslint-env amd, node */ 7 | 8 | // https://github.com/umdjs/umd/blob/master/templates/returnExports.js 9 | (function(root, factory) { 10 | 'use strict'; 11 | if (typeof define === 'function' && define.amd) { 12 | // AMD. Register as an anonymous module. 13 | define([], factory); 14 | } else if (typeof module === 'object' && module.exports) { 15 | // Node. Does not work with strict CommonJS, but 16 | // only CommonJS-like environments that support module.exports, 17 | // like Node. 18 | module.exports = factory(); 19 | } else { 20 | // Browser globals (root is window) 21 | root.AnchorJS = factory(); 22 | root.anchors = new root.AnchorJS(); 23 | } 24 | })(this, function() { 25 | 'use strict'; 26 | function AnchorJS(options) { 27 | this.options = options || {}; 28 | this.elements = []; 29 | 30 | /** 31 | * Assigns options to the internal options object, and provides defaults. 32 | * @param {Object} opts - Options object 33 | */ 34 | function _applyRemainingDefaultOptions(opts) { 35 | opts.icon = opts.hasOwnProperty('icon') ? opts.icon : '\ue9cb'; // Accepts characters (and also URLs?), like '#', '¶', '❡', or '§'. 36 | opts.visible = opts.hasOwnProperty('visible') ? opts.visible : 'hover'; // Also accepts 'always' & 'touch' 37 | opts.placement = opts.hasOwnProperty('placement') 38 | ? opts.placement 39 | : 'right'; // Also accepts 'left' 40 | opts.class = opts.hasOwnProperty('class') ? opts.class : ''; // Accepts any class name. 41 | // Using Math.floor here will ensure the value is Number-cast and an integer. 42 | opts.truncate = opts.hasOwnProperty('truncate') 43 | ? Math.floor(opts.truncate) 44 | : 64; // Accepts any value that can be typecast to a number. 45 | } 46 | 47 | _applyRemainingDefaultOptions(this.options); 48 | 49 | /** 50 | * Checks to see if this device supports touch. Uses criteria pulled from Modernizr: 51 | * https://github.com/Modernizr/Modernizr/blob/da22eb27631fc4957f67607fe6042e85c0a84656/feature-detects/touchevents.js#L40 52 | * @returns {Boolean} - true if the current device supports touch. 53 | */ 54 | this.isTouchDevice = function() { 55 | return !!( 56 | 'ontouchstart' in window || 57 | (window.DocumentTouch && document instanceof DocumentTouch) 58 | ); 59 | }; 60 | 61 | /** 62 | * Add anchor links to page elements. 63 | * @param {String|Array|Nodelist} selector - A CSS selector for targeting the elements you wish to add anchor links 64 | * to. Also accepts an array or nodeList containing the relavant elements. 65 | * @returns {this} - The AnchorJS object 66 | */ 67 | this.add = function(selector) { 68 | var elements, 69 | elsWithIds, 70 | idList, 71 | elementID, 72 | i, 73 | index, 74 | count, 75 | tidyText, 76 | newTidyText, 77 | readableID, 78 | anchor, 79 | visibleOptionToUse, 80 | indexesToDrop = []; 81 | 82 | // We reapply options here because somebody may have overwritten the default options object when setting options. 83 | // For example, this overwrites all options but visible: 84 | // 85 | // anchors.options = { visible: 'always'; } 86 | _applyRemainingDefaultOptions(this.options); 87 | 88 | visibleOptionToUse = this.options.visible; 89 | if (visibleOptionToUse === 'touch') { 90 | visibleOptionToUse = this.isTouchDevice() ? 'always' : 'hover'; 91 | } 92 | 93 | // Provide a sensible default selector, if none is given. 94 | if (!selector) { 95 | selector = 'h2, h3, h4, h5, h6'; 96 | } 97 | 98 | elements = _getElements(selector); 99 | 100 | if (elements.length === 0) { 101 | return this; 102 | } 103 | 104 | _addBaselineStyles(); 105 | 106 | // We produce a list of existing IDs so we don't generate a duplicate. 107 | elsWithIds = document.querySelectorAll('[id]'); 108 | idList = [].map.call(elsWithIds, function assign(el) { 109 | return el.id; 110 | }); 111 | 112 | for (i = 0; i < elements.length; i++) { 113 | if (this.hasAnchorJSLink(elements[i])) { 114 | indexesToDrop.push(i); 115 | continue; 116 | } 117 | 118 | if (elements[i].hasAttribute('id')) { 119 | elementID = elements[i].getAttribute('id'); 120 | } else if (elements[i].hasAttribute('data-anchor-id')) { 121 | elementID = elements[i].getAttribute('data-anchor-id'); 122 | } else { 123 | tidyText = this.urlify(elements[i].textContent); 124 | 125 | // Compare our generated ID to existing IDs (and increment it if needed) 126 | // before we add it to the page. 127 | newTidyText = tidyText; 128 | count = 0; 129 | do { 130 | if (index !== undefined) { 131 | newTidyText = tidyText + '-' + count; 132 | } 133 | 134 | index = idList.indexOf(newTidyText); 135 | count += 1; 136 | } while (index !== -1); 137 | index = undefined; 138 | idList.push(newTidyText); 139 | 140 | elements[i].setAttribute('id', newTidyText); 141 | elementID = newTidyText; 142 | } 143 | 144 | readableID = elementID.replace(/-/g, ' '); 145 | 146 | // The following code builds the following DOM structure in a more effiecient (albeit opaque) way. 147 | // ''; 148 | anchor = document.createElement('a'); 149 | anchor.className = 'anchorjs-link ' + this.options.class; 150 | anchor.href = '#' + elementID; 151 | anchor.setAttribute('aria-label', 'Anchor link for: ' + readableID); 152 | anchor.setAttribute('data-anchorjs-icon', this.options.icon); 153 | 154 | if (visibleOptionToUse === 'always') { 155 | anchor.style.opacity = '1'; 156 | } 157 | 158 | if (this.options.icon === '\ue9cb') { 159 | anchor.style.font = '1em/1 anchorjs-icons'; 160 | 161 | // We set lineHeight = 1 here because the `anchorjs-icons` font family could otherwise affect the 162 | // height of the heading. This isn't the case for icons with `placement: left`, so we restore 163 | // line-height: inherit in that case, ensuring they remain positioned correctly. For more info, 164 | // see https://github.com/bryanbraun/anchorjs/issues/39. 165 | if (this.options.placement === 'left') { 166 | anchor.style.lineHeight = 'inherit'; 167 | } 168 | } 169 | 170 | if (this.options.placement === 'left') { 171 | anchor.style.position = 'absolute'; 172 | anchor.style.marginLeft = '-1em'; 173 | anchor.style.paddingRight = '0.5em'; 174 | elements[i].insertBefore(anchor, elements[i].firstChild); 175 | } else { 176 | // if the option provided is `right` (or anything else). 177 | anchor.style.paddingLeft = '0.375em'; 178 | elements[i].appendChild(anchor); 179 | } 180 | } 181 | 182 | for (i = 0; i < indexesToDrop.length; i++) { 183 | elements.splice(indexesToDrop[i] - i, 1); 184 | } 185 | this.elements = this.elements.concat(elements); 186 | 187 | return this; 188 | }; 189 | 190 | /** 191 | * Removes all anchorjs-links from elements targed by the selector. 192 | * @param {String|Array|Nodelist} selector - A CSS selector string targeting elements with anchor links, 193 | * OR a nodeList / array containing the DOM elements. 194 | * @returns {this} - The AnchorJS object 195 | */ 196 | this.remove = function(selector) { 197 | var index, 198 | domAnchor, 199 | elements = _getElements(selector); 200 | 201 | for (var i = 0; i < elements.length; i++) { 202 | domAnchor = elements[i].querySelector('.anchorjs-link'); 203 | if (domAnchor) { 204 | // Drop the element from our main list, if it's in there. 205 | index = this.elements.indexOf(elements[i]); 206 | if (index !== -1) { 207 | this.elements.splice(index, 1); 208 | } 209 | // Remove the anchor from the DOM. 210 | elements[i].removeChild(domAnchor); 211 | } 212 | } 213 | return this; 214 | }; 215 | 216 | /** 217 | * Removes all anchorjs links. Mostly used for tests. 218 | */ 219 | this.removeAll = function() { 220 | this.remove(this.elements); 221 | }; 222 | 223 | /** 224 | * Urlify - Refine text so it makes a good ID. 225 | * 226 | * To do this, we remove apostrophes, replace nonsafe characters with hyphens, 227 | * remove extra hyphens, truncate, trim hyphens, and make lowercase. 228 | * 229 | * @param {String} text - Any text. Usually pulled from the webpage element we are linking to. 230 | * @returns {String} - hyphen-delimited text for use in IDs and URLs. 231 | */ 232 | this.urlify = function(text) { 233 | // Regex for finding the nonsafe URL characters (many need escaping): & +$,:;=?@"#{}|^~[`%!'<>]./()*\ 234 | var nonsafeChars = /[& +$,:;=?@"#{}|^~[`%!'<>\]\.\/\(\)\*\\]/g, 235 | urlText; 236 | 237 | // The reason we include this _applyRemainingDefaultOptions is so urlify can be called independently, 238 | // even after setting options. This can be useful for tests or other applications. 239 | if (!this.options.truncate) { 240 | _applyRemainingDefaultOptions(this.options); 241 | } 242 | 243 | // Note: we trim hyphens after truncating because truncating can cause dangling hyphens. 244 | // Example string: // " ⚡⚡ Don't forget: URL fragments should be i18n-friendly, hyphenated, short, and clean." 245 | urlText = text 246 | .trim() // "⚡⚡ Don't forget: URL fragments should be i18n-friendly, hyphenated, short, and clean." 247 | .replace(/\'/gi, '') // "⚡⚡ Dont forget: URL fragments should be i18n-friendly, hyphenated, short, and clean." 248 | .replace(nonsafeChars, '-') // "⚡⚡-Dont-forget--URL-fragments-should-be-i18n-friendly--hyphenated--short--and-clean-" 249 | .replace(/-{2,}/g, '-') // "⚡⚡-Dont-forget-URL-fragments-should-be-i18n-friendly-hyphenated-short-and-clean-" 250 | .substring(0, this.options.truncate) // "⚡⚡-Dont-forget-URL-fragments-should-be-i18n-friendly-hyphenated-" 251 | .replace(/^-+|-+$/gm, '') // "⚡⚡-Dont-forget-URL-fragments-should-be-i18n-friendly-hyphenated" 252 | .toLowerCase(); // "⚡⚡-dont-forget-url-fragments-should-be-i18n-friendly-hyphenated" 253 | 254 | return urlText; 255 | }; 256 | 257 | /** 258 | * Determines if this element already has an AnchorJS link on it. 259 | * Uses this technique: http://stackoverflow.com/a/5898748/1154642 260 | * @param {HTMLElemnt} el - a DOM node 261 | * @returns {Boolean} true/false 262 | */ 263 | this.hasAnchorJSLink = function(el) { 264 | var hasLeftAnchor = 265 | el.firstChild && 266 | (' ' + el.firstChild.className + ' ').indexOf(' anchorjs-link ') > -1, 267 | hasRightAnchor = 268 | el.lastChild && 269 | (' ' + el.lastChild.className + ' ').indexOf(' anchorjs-link ') > -1; 270 | 271 | return hasLeftAnchor || hasRightAnchor || false; 272 | }; 273 | 274 | /** 275 | * Turns a selector, nodeList, or array of elements into an array of elements (so we can use array methods). 276 | * It also throws errors on any other inputs. Used to handle inputs to .add and .remove. 277 | * @param {String|Array|Nodelist} input - A CSS selector string targeting elements with anchor links, 278 | * OR a nodeList / array containing the DOM elements. 279 | * @returns {Array} - An array containing the elements we want. 280 | */ 281 | function _getElements(input) { 282 | var elements; 283 | if (typeof input === 'string' || input instanceof String) { 284 | // See https://davidwalsh.name/nodelist-array for the technique transforming nodeList -> Array. 285 | elements = [].slice.call(document.querySelectorAll(input)); 286 | // I checked the 'input instanceof NodeList' test in IE9 and modern browsers and it worked for me. 287 | } else if (Array.isArray(input) || input instanceof NodeList) { 288 | elements = [].slice.call(input); 289 | } else { 290 | throw new Error('The selector provided to AnchorJS was invalid.'); 291 | } 292 | return elements; 293 | } 294 | 295 | /** 296 | * _addBaselineStyles 297 | * Adds baseline styles to the page, used by all AnchorJS links irregardless of configuration. 298 | */ 299 | function _addBaselineStyles() { 300 | // We don't want to add global baseline styles if they've been added before. 301 | if (document.head.querySelector('style.anchorjs') !== null) { 302 | return; 303 | } 304 | 305 | var style = document.createElement('style'), 306 | linkRule = 307 | ' .anchorjs-link {' + 308 | ' opacity: 0;' + 309 | ' text-decoration: none;' + 310 | ' -webkit-font-smoothing: antialiased;' + 311 | ' -moz-osx-font-smoothing: grayscale;' + 312 | ' }', 313 | hoverRule = 314 | ' *:hover > .anchorjs-link,' + 315 | ' .anchorjs-link:focus {' + 316 | ' opacity: 1;' + 317 | ' }', 318 | anchorjsLinkFontFace = 319 | ' @font-face {' + 320 | ' font-family: "anchorjs-icons";' + // Icon from icomoon; 10px wide & 10px tall; 2 empty below & 4 above 321 | ' src: url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype");' + 322 | ' }', 323 | pseudoElContent = 324 | ' [data-anchorjs-icon]::after {' + 325 | ' content: attr(data-anchorjs-icon);' + 326 | ' }', 327 | firstStyleEl; 328 | 329 | style.className = 'anchorjs'; 330 | style.appendChild(document.createTextNode('')); // Necessary for Webkit. 331 | 332 | // We place it in the head with the other style tags, if possible, so as to 333 | // not look out of place. We insert before the others so these styles can be 334 | // overridden if necessary. 335 | firstStyleEl = document.head.querySelector('[rel="stylesheet"], style'); 336 | if (firstStyleEl === undefined) { 337 | document.head.appendChild(style); 338 | } else { 339 | document.head.insertBefore(style, firstStyleEl); 340 | } 341 | 342 | style.sheet.insertRule(linkRule, style.sheet.cssRules.length); 343 | style.sheet.insertRule(hoverRule, style.sheet.cssRules.length); 344 | style.sheet.insertRule(pseudoElContent, style.sheet.cssRules.length); 345 | style.sheet.insertRule(anchorjsLinkFontFace, style.sheet.cssRules.length); 346 | } 347 | } 348 | 349 | return AnchorJS; 350 | }); 351 | -------------------------------------------------------------------------------- /docs/assets/bass-addons.css: -------------------------------------------------------------------------------- 1 | .input { 2 | font-family: inherit; 3 | display: block; 4 | width: 100%; 5 | height: 2rem; 6 | padding: .5rem; 7 | margin-bottom: 1rem; 8 | border: 1px solid #ccc; 9 | font-size: .875rem; 10 | border-radius: 3px; 11 | box-sizing: border-box; 12 | } 13 | -------------------------------------------------------------------------------- /docs/assets/bass.css: -------------------------------------------------------------------------------- 1 | /*! Basscss | http://basscss.com | MIT License */ 2 | 3 | .h1{ font-size: 2rem } 4 | .h2{ font-size: 1.5rem } 5 | .h3{ font-size: 1.25rem } 6 | .h4{ font-size: 1rem } 7 | .h5{ font-size: .875rem } 8 | .h6{ font-size: .75rem } 9 | 10 | .font-family-inherit{ font-family:inherit } 11 | .font-size-inherit{ font-size:inherit } 12 | .text-decoration-none{ text-decoration:none } 13 | 14 | .bold{ font-weight: bold; font-weight: bold } 15 | .regular{ font-weight:normal } 16 | .italic{ font-style:italic } 17 | .caps{ text-transform:uppercase; letter-spacing: .2em; } 18 | 19 | .left-align{ text-align:left } 20 | .center{ text-align:center } 21 | .right-align{ text-align:right } 22 | .justify{ text-align:justify } 23 | 24 | .nowrap{ white-space:nowrap } 25 | .break-word{ word-wrap:break-word } 26 | 27 | .line-height-1{ line-height: 1 } 28 | .line-height-2{ line-height: 1.125 } 29 | .line-height-3{ line-height: 1.25 } 30 | .line-height-4{ line-height: 1.5 } 31 | 32 | .list-style-none{ list-style:none } 33 | .underline{ text-decoration:underline } 34 | 35 | .truncate{ 36 | max-width:100%; 37 | overflow:hidden; 38 | text-overflow:ellipsis; 39 | white-space:nowrap; 40 | } 41 | 42 | .list-reset{ 43 | list-style:none; 44 | padding-left:0; 45 | } 46 | 47 | .inline{ display:inline } 48 | .block{ display:block } 49 | .inline-block{ display:inline-block } 50 | .table{ display:table } 51 | .table-cell{ display:table-cell } 52 | 53 | .overflow-hidden{ overflow:hidden } 54 | .overflow-scroll{ overflow:scroll } 55 | .overflow-auto{ overflow:auto } 56 | 57 | .clearfix:before, 58 | .clearfix:after{ 59 | content:" "; 60 | display:table 61 | } 62 | .clearfix:after{ clear:both } 63 | 64 | .left{ float:left } 65 | .right{ float:right } 66 | 67 | .fit{ max-width:100% } 68 | 69 | .max-width-1{ max-width: 24rem } 70 | .max-width-2{ max-width: 32rem } 71 | .max-width-3{ max-width: 48rem } 72 | .max-width-4{ max-width: 64rem } 73 | 74 | .border-box{ box-sizing:border-box } 75 | 76 | .align-baseline{ vertical-align:baseline } 77 | .align-top{ vertical-align:top } 78 | .align-middle{ vertical-align:middle } 79 | .align-bottom{ vertical-align:bottom } 80 | 81 | .m0{ margin:0 } 82 | .mt0{ margin-top:0 } 83 | .mr0{ margin-right:0 } 84 | .mb0{ margin-bottom:0 } 85 | .ml0{ margin-left:0 } 86 | .mx0{ margin-left:0; margin-right:0 } 87 | .my0{ margin-top:0; margin-bottom:0 } 88 | 89 | .m1{ margin: .5rem } 90 | .mt1{ margin-top: .5rem } 91 | .mr1{ margin-right: .5rem } 92 | .mb1{ margin-bottom: .5rem } 93 | .ml1{ margin-left: .5rem } 94 | .mx1{ margin-left: .5rem; margin-right: .5rem } 95 | .my1{ margin-top: .5rem; margin-bottom: .5rem } 96 | 97 | .m2{ margin: 1rem } 98 | .mt2{ margin-top: 1rem } 99 | .mr2{ margin-right: 1rem } 100 | .mb2{ margin-bottom: 1rem } 101 | .ml2{ margin-left: 1rem } 102 | .mx2{ margin-left: 1rem; margin-right: 1rem } 103 | .my2{ margin-top: 1rem; margin-bottom: 1rem } 104 | 105 | .m3{ margin: 2rem } 106 | .mt3{ margin-top: 2rem } 107 | .mr3{ margin-right: 2rem } 108 | .mb3{ margin-bottom: 2rem } 109 | .ml3{ margin-left: 2rem } 110 | .mx3{ margin-left: 2rem; margin-right: 2rem } 111 | .my3{ margin-top: 2rem; margin-bottom: 2rem } 112 | 113 | .m4{ margin: 4rem } 114 | .mt4{ margin-top: 4rem } 115 | .mr4{ margin-right: 4rem } 116 | .mb4{ margin-bottom: 4rem } 117 | .ml4{ margin-left: 4rem } 118 | .mx4{ margin-left: 4rem; margin-right: 4rem } 119 | .my4{ margin-top: 4rem; margin-bottom: 4rem } 120 | 121 | .mxn1{ margin-left: -.5rem; margin-right: -.5rem; } 122 | .mxn2{ margin-left: -1rem; margin-right: -1rem; } 123 | .mxn3{ margin-left: -2rem; margin-right: -2rem; } 124 | .mxn4{ margin-left: -4rem; margin-right: -4rem; } 125 | 126 | .ml-auto{ margin-left:auto } 127 | .mr-auto{ margin-right:auto } 128 | .mx-auto{ margin-left:auto; margin-right:auto; } 129 | 130 | .p0{ padding:0 } 131 | .pt0{ padding-top:0 } 132 | .pr0{ padding-right:0 } 133 | .pb0{ padding-bottom:0 } 134 | .pl0{ padding-left:0 } 135 | .px0{ padding-left:0; padding-right:0 } 136 | .py0{ padding-top:0; padding-bottom:0 } 137 | 138 | .p1{ padding: .5rem } 139 | .pt1{ padding-top: .5rem } 140 | .pr1{ padding-right: .5rem } 141 | .pb1{ padding-bottom: .5rem } 142 | .pl1{ padding-left: .5rem } 143 | .py1{ padding-top: .5rem; padding-bottom: .5rem } 144 | .px1{ padding-left: .5rem; padding-right: .5rem } 145 | 146 | .p2{ padding: 1rem } 147 | .pt2{ padding-top: 1rem } 148 | .pr2{ padding-right: 1rem } 149 | .pb2{ padding-bottom: 1rem } 150 | .pl2{ padding-left: 1rem } 151 | .py2{ padding-top: 1rem; padding-bottom: 1rem } 152 | .px2{ padding-left: 1rem; padding-right: 1rem } 153 | 154 | .p3{ padding: 2rem } 155 | .pt3{ padding-top: 2rem } 156 | .pr3{ padding-right: 2rem } 157 | .pb3{ padding-bottom: 2rem } 158 | .pl3{ padding-left: 2rem } 159 | .py3{ padding-top: 2rem; padding-bottom: 2rem } 160 | .px3{ padding-left: 2rem; padding-right: 2rem } 161 | 162 | .p4{ padding: 4rem } 163 | .pt4{ padding-top: 4rem } 164 | .pr4{ padding-right: 4rem } 165 | .pb4{ padding-bottom: 4rem } 166 | .pl4{ padding-left: 4rem } 167 | .py4{ padding-top: 4rem; padding-bottom: 4rem } 168 | .px4{ padding-left: 4rem; padding-right: 4rem } 169 | 170 | .col{ 171 | float:left; 172 | box-sizing:border-box; 173 | } 174 | 175 | .col-right{ 176 | float:right; 177 | box-sizing:border-box; 178 | } 179 | 180 | .col-1{ 181 | width:8.33333%; 182 | } 183 | 184 | .col-2{ 185 | width:16.66667%; 186 | } 187 | 188 | .col-3{ 189 | width:25%; 190 | } 191 | 192 | .col-4{ 193 | width:33.33333%; 194 | } 195 | 196 | .col-5{ 197 | width:41.66667%; 198 | } 199 | 200 | .col-6{ 201 | width:50%; 202 | } 203 | 204 | .col-7{ 205 | width:58.33333%; 206 | } 207 | 208 | .col-8{ 209 | width:66.66667%; 210 | } 211 | 212 | .col-9{ 213 | width:75%; 214 | } 215 | 216 | .col-10{ 217 | width:83.33333%; 218 | } 219 | 220 | .col-11{ 221 | width:91.66667%; 222 | } 223 | 224 | .col-12{ 225 | width:100%; 226 | } 227 | @media (min-width: 40em){ 228 | 229 | .sm-col{ 230 | float:left; 231 | box-sizing:border-box; 232 | } 233 | 234 | .sm-col-right{ 235 | float:right; 236 | box-sizing:border-box; 237 | } 238 | 239 | .sm-col-1{ 240 | width:8.33333%; 241 | } 242 | 243 | .sm-col-2{ 244 | width:16.66667%; 245 | } 246 | 247 | .sm-col-3{ 248 | width:25%; 249 | } 250 | 251 | .sm-col-4{ 252 | width:33.33333%; 253 | } 254 | 255 | .sm-col-5{ 256 | width:41.66667%; 257 | } 258 | 259 | .sm-col-6{ 260 | width:50%; 261 | } 262 | 263 | .sm-col-7{ 264 | width:58.33333%; 265 | } 266 | 267 | .sm-col-8{ 268 | width:66.66667%; 269 | } 270 | 271 | .sm-col-9{ 272 | width:75%; 273 | } 274 | 275 | .sm-col-10{ 276 | width:83.33333%; 277 | } 278 | 279 | .sm-col-11{ 280 | width:91.66667%; 281 | } 282 | 283 | .sm-col-12{ 284 | width:100%; 285 | } 286 | 287 | } 288 | @media (min-width: 52em){ 289 | 290 | .md-col{ 291 | float:left; 292 | box-sizing:border-box; 293 | } 294 | 295 | .md-col-right{ 296 | float:right; 297 | box-sizing:border-box; 298 | } 299 | 300 | .md-col-1{ 301 | width:8.33333%; 302 | } 303 | 304 | .md-col-2{ 305 | width:16.66667%; 306 | } 307 | 308 | .md-col-3{ 309 | width:25%; 310 | } 311 | 312 | .md-col-4{ 313 | width:33.33333%; 314 | } 315 | 316 | .md-col-5{ 317 | width:41.66667%; 318 | } 319 | 320 | .md-col-6{ 321 | width:50%; 322 | } 323 | 324 | .md-col-7{ 325 | width:58.33333%; 326 | } 327 | 328 | .md-col-8{ 329 | width:66.66667%; 330 | } 331 | 332 | .md-col-9{ 333 | width:75%; 334 | } 335 | 336 | .md-col-10{ 337 | width:83.33333%; 338 | } 339 | 340 | .md-col-11{ 341 | width:91.66667%; 342 | } 343 | 344 | .md-col-12{ 345 | width:100%; 346 | } 347 | 348 | } 349 | @media (min-width: 64em){ 350 | 351 | .lg-col{ 352 | float:left; 353 | box-sizing:border-box; 354 | } 355 | 356 | .lg-col-right{ 357 | float:right; 358 | box-sizing:border-box; 359 | } 360 | 361 | .lg-col-1{ 362 | width:8.33333%; 363 | } 364 | 365 | .lg-col-2{ 366 | width:16.66667%; 367 | } 368 | 369 | .lg-col-3{ 370 | width:25%; 371 | } 372 | 373 | .lg-col-4{ 374 | width:33.33333%; 375 | } 376 | 377 | .lg-col-5{ 378 | width:41.66667%; 379 | } 380 | 381 | .lg-col-6{ 382 | width:50%; 383 | } 384 | 385 | .lg-col-7{ 386 | width:58.33333%; 387 | } 388 | 389 | .lg-col-8{ 390 | width:66.66667%; 391 | } 392 | 393 | .lg-col-9{ 394 | width:75%; 395 | } 396 | 397 | .lg-col-10{ 398 | width:83.33333%; 399 | } 400 | 401 | .lg-col-11{ 402 | width:91.66667%; 403 | } 404 | 405 | .lg-col-12{ 406 | width:100%; 407 | } 408 | 409 | } 410 | .flex{ display:-webkit-box; display:-webkit-flex; display:-ms-flexbox; display:flex } 411 | 412 | @media (min-width: 40em){ 413 | .sm-flex{ display:-webkit-box; display:-webkit-flex; display:-ms-flexbox; display:flex } 414 | } 415 | 416 | @media (min-width: 52em){ 417 | .md-flex{ display:-webkit-box; display:-webkit-flex; display:-ms-flexbox; display:flex } 418 | } 419 | 420 | @media (min-width: 64em){ 421 | .lg-flex{ display:-webkit-box; display:-webkit-flex; display:-ms-flexbox; display:flex } 422 | } 423 | 424 | .flex-column{ -webkit-box-orient:vertical; -webkit-box-direction:normal; -webkit-flex-direction:column; -ms-flex-direction:column; flex-direction:column } 425 | .flex-wrap{ -webkit-flex-wrap:wrap; -ms-flex-wrap:wrap; flex-wrap:wrap } 426 | 427 | .items-start{ -webkit-box-align:start; -webkit-align-items:flex-start; -ms-flex-align:start; -ms-grid-row-align:flex-start; align-items:flex-start } 428 | .items-end{ -webkit-box-align:end; -webkit-align-items:flex-end; -ms-flex-align:end; -ms-grid-row-align:flex-end; align-items:flex-end } 429 | .items-center{ -webkit-box-align:center; -webkit-align-items:center; -ms-flex-align:center; -ms-grid-row-align:center; align-items:center } 430 | .items-baseline{ -webkit-box-align:baseline; -webkit-align-items:baseline; -ms-flex-align:baseline; -ms-grid-row-align:baseline; align-items:baseline } 431 | .items-stretch{ -webkit-box-align:stretch; -webkit-align-items:stretch; -ms-flex-align:stretch; -ms-grid-row-align:stretch; align-items:stretch } 432 | 433 | .self-start{ -webkit-align-self:flex-start; -ms-flex-item-align:start; align-self:flex-start } 434 | .self-end{ -webkit-align-self:flex-end; -ms-flex-item-align:end; align-self:flex-end } 435 | .self-center{ -webkit-align-self:center; -ms-flex-item-align:center; align-self:center } 436 | .self-baseline{ -webkit-align-self:baseline; -ms-flex-item-align:baseline; align-self:baseline } 437 | .self-stretch{ -webkit-align-self:stretch; -ms-flex-item-align:stretch; align-self:stretch } 438 | 439 | .justify-start{ -webkit-box-pack:start; -webkit-justify-content:flex-start; -ms-flex-pack:start; justify-content:flex-start } 440 | .justify-end{ -webkit-box-pack:end; -webkit-justify-content:flex-end; -ms-flex-pack:end; justify-content:flex-end } 441 | .justify-center{ -webkit-box-pack:center; -webkit-justify-content:center; -ms-flex-pack:center; justify-content:center } 442 | .justify-between{ -webkit-box-pack:justify; -webkit-justify-content:space-between; -ms-flex-pack:justify; justify-content:space-between } 443 | .justify-around{ -webkit-justify-content:space-around; -ms-flex-pack:distribute; justify-content:space-around } 444 | 445 | .content-start{ -webkit-align-content:flex-start; -ms-flex-line-pack:start; align-content:flex-start } 446 | .content-end{ -webkit-align-content:flex-end; -ms-flex-line-pack:end; align-content:flex-end } 447 | .content-center{ -webkit-align-content:center; -ms-flex-line-pack:center; align-content:center } 448 | .content-between{ -webkit-align-content:space-between; -ms-flex-line-pack:justify; align-content:space-between } 449 | .content-around{ -webkit-align-content:space-around; -ms-flex-line-pack:distribute; align-content:space-around } 450 | .content-stretch{ -webkit-align-content:stretch; -ms-flex-line-pack:stretch; align-content:stretch } 451 | .flex-auto{ 452 | -webkit-box-flex:1; 453 | -webkit-flex:1 1 auto; 454 | -ms-flex:1 1 auto; 455 | flex:1 1 auto; 456 | min-width:0; 457 | min-height:0; 458 | } 459 | .flex-none{ -webkit-box-flex:0; -webkit-flex:none; -ms-flex:none; flex:none } 460 | .fs0{ flex-shrink: 0 } 461 | 462 | .order-0{ -webkit-box-ordinal-group:1; -webkit-order:0; -ms-flex-order:0; order:0 } 463 | .order-1{ -webkit-box-ordinal-group:2; -webkit-order:1; -ms-flex-order:1; order:1 } 464 | .order-2{ -webkit-box-ordinal-group:3; -webkit-order:2; -ms-flex-order:2; order:2 } 465 | .order-3{ -webkit-box-ordinal-group:4; -webkit-order:3; -ms-flex-order:3; order:3 } 466 | .order-last{ -webkit-box-ordinal-group:100000; -webkit-order:99999; -ms-flex-order:99999; order:99999 } 467 | 468 | .relative{ position:relative } 469 | .absolute{ position:absolute } 470 | .fixed{ position:fixed } 471 | 472 | .top-0{ top:0 } 473 | .right-0{ right:0 } 474 | .bottom-0{ bottom:0 } 475 | .left-0{ left:0 } 476 | 477 | .z1{ z-index: 1 } 478 | .z2{ z-index: 2 } 479 | .z3{ z-index: 3 } 480 | .z4{ z-index: 4 } 481 | 482 | .border{ 483 | border-style:solid; 484 | border-width: 1px; 485 | } 486 | 487 | .border-top{ 488 | border-top-style:solid; 489 | border-top-width: 1px; 490 | } 491 | 492 | .border-right{ 493 | border-right-style:solid; 494 | border-right-width: 1px; 495 | } 496 | 497 | .border-bottom{ 498 | border-bottom-style:solid; 499 | border-bottom-width: 1px; 500 | } 501 | 502 | .border-left{ 503 | border-left-style:solid; 504 | border-left-width: 1px; 505 | } 506 | 507 | .border-none{ border:0 } 508 | 509 | .rounded{ border-radius: 3px } 510 | .circle{ border-radius:50% } 511 | 512 | .rounded-top{ border-radius: 3px 3px 0 0 } 513 | .rounded-right{ border-radius: 0 3px 3px 0 } 514 | .rounded-bottom{ border-radius: 0 0 3px 3px } 515 | .rounded-left{ border-radius: 3px 0 0 3px } 516 | 517 | .not-rounded{ border-radius:0 } 518 | 519 | .hide{ 520 | position:absolute !important; 521 | height:1px; 522 | width:1px; 523 | overflow:hidden; 524 | clip:rect(1px, 1px, 1px, 1px); 525 | } 526 | 527 | @media (max-width: 40em){ 528 | .xs-hide{ display:none !important } 529 | } 530 | 531 | @media (min-width: 40em) and (max-width: 52em){ 532 | .sm-hide{ display:none !important } 533 | } 534 | 535 | @media (min-width: 52em) and (max-width: 64em){ 536 | .md-hide{ display:none !important } 537 | } 538 | 539 | @media (min-width: 64em){ 540 | .lg-hide{ display:none !important } 541 | } 542 | 543 | .display-none{ display:none !important } 544 | 545 | -------------------------------------------------------------------------------- /docs/assets/fonts/EOT/SourceCodePro-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mljs/xgboost/7766ea17ed7b42b9ae10746c95e26c3480724721/docs/assets/fonts/EOT/SourceCodePro-Bold.eot -------------------------------------------------------------------------------- /docs/assets/fonts/EOT/SourceCodePro-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mljs/xgboost/7766ea17ed7b42b9ae10746c95e26c3480724721/docs/assets/fonts/EOT/SourceCodePro-Regular.eot -------------------------------------------------------------------------------- /docs/assets/fonts/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | 5 | This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /docs/assets/fonts/OTF/SourceCodePro-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mljs/xgboost/7766ea17ed7b42b9ae10746c95e26c3480724721/docs/assets/fonts/OTF/SourceCodePro-Bold.otf -------------------------------------------------------------------------------- /docs/assets/fonts/OTF/SourceCodePro-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mljs/xgboost/7766ea17ed7b42b9ae10746c95e26c3480724721/docs/assets/fonts/OTF/SourceCodePro-Regular.otf -------------------------------------------------------------------------------- /docs/assets/fonts/TTF/SourceCodePro-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mljs/xgboost/7766ea17ed7b42b9ae10746c95e26c3480724721/docs/assets/fonts/TTF/SourceCodePro-Bold.ttf -------------------------------------------------------------------------------- /docs/assets/fonts/TTF/SourceCodePro-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mljs/xgboost/7766ea17ed7b42b9ae10746c95e26c3480724721/docs/assets/fonts/TTF/SourceCodePro-Regular.ttf -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF/OTF/SourceCodePro-Bold.otf.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mljs/xgboost/7766ea17ed7b42b9ae10746c95e26c3480724721/docs/assets/fonts/WOFF/OTF/SourceCodePro-Bold.otf.woff -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF/OTF/SourceCodePro-Regular.otf.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mljs/xgboost/7766ea17ed7b42b9ae10746c95e26c3480724721/docs/assets/fonts/WOFF/OTF/SourceCodePro-Regular.otf.woff -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF/TTF/SourceCodePro-Bold.ttf.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mljs/xgboost/7766ea17ed7b42b9ae10746c95e26c3480724721/docs/assets/fonts/WOFF/TTF/SourceCodePro-Bold.ttf.woff -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF/TTF/SourceCodePro-Regular.ttf.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mljs/xgboost/7766ea17ed7b42b9ae10746c95e26c3480724721/docs/assets/fonts/WOFF/TTF/SourceCodePro-Regular.ttf.woff -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF2/OTF/SourceCodePro-Bold.otf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mljs/xgboost/7766ea17ed7b42b9ae10746c95e26c3480724721/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Bold.otf.woff2 -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF2/OTF/SourceCodePro-Regular.otf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mljs/xgboost/7766ea17ed7b42b9ae10746c95e26c3480724721/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Regular.otf.woff2 -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF2/TTF/SourceCodePro-Bold.ttf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mljs/xgboost/7766ea17ed7b42b9ae10746c95e26c3480724721/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Bold.ttf.woff2 -------------------------------------------------------------------------------- /docs/assets/fonts/WOFF2/TTF/SourceCodePro-Regular.ttf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mljs/xgboost/7766ea17ed7b42b9ae10746c95e26c3480724721/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Regular.ttf.woff2 -------------------------------------------------------------------------------- /docs/assets/fonts/source-code-pro.css: -------------------------------------------------------------------------------- 1 | @font-face{ 2 | font-family: 'Source Code Pro'; 3 | font-weight: 400; 4 | font-style: normal; 5 | font-stretch: normal; 6 | src: url('EOT/SourceCodePro-Regular.eot') format('embedded-opentype'), 7 | url('WOFF2/TTF/SourceCodePro-Regular.ttf.woff2') format('woff2'), 8 | url('WOFF/OTF/SourceCodePro-Regular.otf.woff') format('woff'), 9 | url('OTF/SourceCodePro-Regular.otf') format('opentype'), 10 | url('TTF/SourceCodePro-Regular.ttf') format('truetype'); 11 | } 12 | 13 | @font-face{ 14 | font-family: 'Source Code Pro'; 15 | font-weight: 700; 16 | font-style: normal; 17 | font-stretch: normal; 18 | src: url('EOT/SourceCodePro-Bold.eot') format('embedded-opentype'), 19 | url('WOFF2/TTF/SourceCodePro-Bold.ttf.woff2') format('woff2'), 20 | url('WOFF/OTF/SourceCodePro-Bold.otf.woff') format('woff'), 21 | url('OTF/SourceCodePro-Bold.otf') format('opentype'), 22 | url('TTF/SourceCodePro-Bold.ttf') format('truetype'); 23 | } 24 | -------------------------------------------------------------------------------- /docs/assets/github.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | github.com style (c) Vasily Polovnyov 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | color: #333; 12 | background: #f8f8f8; 13 | -webkit-text-size-adjust: none; 14 | } 15 | 16 | .hljs-comment, 17 | .diff .hljs-header, 18 | .hljs-javadoc { 19 | color: #998; 20 | font-style: italic; 21 | } 22 | 23 | .hljs-keyword, 24 | .css .rule .hljs-keyword, 25 | .hljs-winutils, 26 | .nginx .hljs-title, 27 | .hljs-subst, 28 | .hljs-request, 29 | .hljs-status { 30 | color: #1184CE; 31 | } 32 | 33 | .hljs-number, 34 | .hljs-hexcolor, 35 | .ruby .hljs-constant { 36 | color: #ed225d; 37 | } 38 | 39 | .hljs-string, 40 | .hljs-tag .hljs-value, 41 | .hljs-phpdoc, 42 | .hljs-dartdoc, 43 | .tex .hljs-formula { 44 | color: #ed225d; 45 | } 46 | 47 | .hljs-title, 48 | .hljs-id, 49 | .scss .hljs-preprocessor { 50 | color: #900; 51 | font-weight: bold; 52 | } 53 | 54 | .hljs-list .hljs-keyword, 55 | .hljs-subst { 56 | font-weight: normal; 57 | } 58 | 59 | .hljs-class .hljs-title, 60 | .hljs-type, 61 | .vhdl .hljs-literal, 62 | .tex .hljs-command { 63 | color: #458; 64 | font-weight: bold; 65 | } 66 | 67 | .hljs-tag, 68 | .hljs-tag .hljs-title, 69 | .hljs-rules .hljs-property, 70 | .django .hljs-tag .hljs-keyword { 71 | color: #000080; 72 | font-weight: normal; 73 | } 74 | 75 | .hljs-attribute, 76 | .hljs-variable, 77 | .lisp .hljs-body { 78 | color: #008080; 79 | } 80 | 81 | .hljs-regexp { 82 | color: #009926; 83 | } 84 | 85 | .hljs-symbol, 86 | .ruby .hljs-symbol .hljs-string, 87 | .lisp .hljs-keyword, 88 | .clojure .hljs-keyword, 89 | .scheme .hljs-keyword, 90 | .tex .hljs-special, 91 | .hljs-prompt { 92 | color: #990073; 93 | } 94 | 95 | .hljs-built_in { 96 | color: #0086b3; 97 | } 98 | 99 | .hljs-preprocessor, 100 | .hljs-pragma, 101 | .hljs-pi, 102 | .hljs-doctype, 103 | .hljs-shebang, 104 | .hljs-cdata { 105 | color: #999; 106 | font-weight: bold; 107 | } 108 | 109 | .hljs-deletion { 110 | background: #fdd; 111 | } 112 | 113 | .hljs-addition { 114 | background: #dfd; 115 | } 116 | 117 | .diff .hljs-change { 118 | background: #0086b3; 119 | } 120 | 121 | .hljs-chunk { 122 | color: #aaa; 123 | } 124 | -------------------------------------------------------------------------------- /docs/assets/site.js: -------------------------------------------------------------------------------- 1 | /* global anchors */ 2 | 3 | // add anchor links to headers 4 | anchors.options.placement = 'left'; 5 | anchors.add('h3'); 6 | 7 | // Filter UI 8 | var tocElements = document.getElementById('toc').getElementsByTagName('li'); 9 | 10 | document.getElementById('filter-input').addEventListener('keyup', function(e) { 11 | var i, element, children; 12 | 13 | // enter key 14 | if (e.keyCode === 13) { 15 | // go to the first displayed item in the toc 16 | for (i = 0; i < tocElements.length; i++) { 17 | element = tocElements[i]; 18 | if (!element.classList.contains('display-none')) { 19 | location.replace(element.firstChild.href); 20 | return e.preventDefault(); 21 | } 22 | } 23 | } 24 | 25 | var match = function() { 26 | return true; 27 | }; 28 | 29 | var value = this.value.toLowerCase(); 30 | 31 | if (!value.match(/^\s*$/)) { 32 | match = function(element) { 33 | var html = element.firstChild.innerHTML; 34 | return html && html.toLowerCase().indexOf(value) !== -1; 35 | }; 36 | } 37 | 38 | for (i = 0; i < tocElements.length; i++) { 39 | element = tocElements[i]; 40 | children = Array.from(element.getElementsByTagName('li')); 41 | if (match(element) || children.some(match)) { 42 | element.classList.remove('display-none'); 43 | } else { 44 | element.classList.add('display-none'); 45 | } 46 | } 47 | }); 48 | 49 | var items = document.getElementsByClassName('toggle-sibling'); 50 | for (var j = 0; j < items.length; j++) { 51 | items[j].addEventListener('click', toggleSibling); 52 | } 53 | 54 | function toggleSibling() { 55 | var stepSibling = this.parentNode.getElementsByClassName('toggle-target')[0]; 56 | var icon = this.getElementsByClassName('icon')[0]; 57 | var klass = 'display-none'; 58 | if (stepSibling.classList.contains(klass)) { 59 | stepSibling.classList.remove(klass); 60 | icon.innerHTML = '▾'; 61 | } else { 62 | stepSibling.classList.add(klass); 63 | icon.innerHTML = '▸'; 64 | } 65 | } 66 | 67 | function showHashTarget(targetId) { 68 | if (targetId) { 69 | var hashTarget = document.getElementById(targetId); 70 | // new target is hidden 71 | if ( 72 | hashTarget && 73 | hashTarget.offsetHeight === 0 && 74 | hashTarget.parentNode.parentNode.classList.contains('display-none') 75 | ) { 76 | hashTarget.parentNode.parentNode.classList.remove('display-none'); 77 | } 78 | } 79 | } 80 | 81 | function scrollIntoView(targetId) { 82 | // Only scroll to element if we don't have a stored scroll position. 83 | if (targetId && !history.state) { 84 | var hashTarget = document.getElementById(targetId); 85 | if (hashTarget) { 86 | hashTarget.scrollIntoView(); 87 | } 88 | } 89 | } 90 | 91 | function gotoCurrentTarget() { 92 | showHashTarget(location.hash.substring(1)); 93 | scrollIntoView(location.hash.substring(1)); 94 | } 95 | 96 | window.addEventListener('hashchange', gotoCurrentTarget); 97 | gotoCurrentTarget(); 98 | 99 | var toclinks = document.getElementsByClassName('pre-open'); 100 | for (var k = 0; k < toclinks.length; k++) { 101 | toclinks[k].addEventListener('mousedown', preOpen, false); 102 | } 103 | 104 | function preOpen() { 105 | showHashTarget(this.hash.substring(1)); 106 | } 107 | 108 | var split_left = document.querySelector('#split-left'); 109 | var split_right = document.querySelector('#split-right'); 110 | var split_parent = split_left.parentNode; 111 | var cw_with_sb = split_left.clientWidth; 112 | split_left.style.overflow = 'hidden'; 113 | var cw_without_sb = split_left.clientWidth; 114 | split_left.style.overflow = ''; 115 | 116 | Split(['#split-left', '#split-right'], { 117 | elementStyle: function(dimension, size, gutterSize) { 118 | return { 119 | 'flex-basis': 'calc(' + size + '% - ' + gutterSize + 'px)' 120 | }; 121 | }, 122 | gutterStyle: function(dimension, gutterSize) { 123 | return { 124 | 'flex-basis': gutterSize + 'px' 125 | }; 126 | }, 127 | gutterSize: 20, 128 | sizes: [33, 67] 129 | }); 130 | 131 | // Chrome doesn't remember scroll position properly so do it ourselves. 132 | // Also works on Firefox and Edge. 133 | 134 | function updateState() { 135 | history.replaceState( 136 | { 137 | left_top: split_left.scrollTop, 138 | right_top: split_right.scrollTop 139 | }, 140 | document.title 141 | ); 142 | } 143 | 144 | function loadState(ev) { 145 | if (ev) { 146 | // Edge doesn't replace change history.state on popstate. 147 | history.replaceState(ev.state, document.title); 148 | } 149 | if (history.state) { 150 | split_left.scrollTop = history.state.left_top; 151 | split_right.scrollTop = history.state.right_top; 152 | } 153 | } 154 | 155 | window.addEventListener('load', function() { 156 | // Restore after Firefox scrolls to hash. 157 | setTimeout(function() { 158 | loadState(); 159 | // Update with initial scroll position. 160 | updateState(); 161 | // Update scroll positions only after we've loaded because Firefox 162 | // emits an initial scroll event with 0. 163 | split_left.addEventListener('scroll', updateState); 164 | split_right.addEventListener('scroll', updateState); 165 | }, 1); 166 | }); 167 | 168 | window.addEventListener('popstate', loadState); 169 | -------------------------------------------------------------------------------- /docs/assets/split.css: -------------------------------------------------------------------------------- 1 | .gutter { 2 | background-color: #f5f5f5; 3 | background-repeat: no-repeat; 4 | background-position: 50%; 5 | } 6 | 7 | .gutter.gutter-vertical { 8 | background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFAQMAAABo7865AAAABlBMVEVHcEzMzMzyAv2sAAAAAXRSTlMAQObYZgAAABBJREFUeF5jOAMEEAIEEFwAn3kMwcB6I2AAAAAASUVORK5CYII='); 9 | cursor: ns-resize; 10 | } 11 | 12 | .gutter.gutter-horizontal { 13 | background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg=='); 14 | cursor: ew-resize; 15 | } 16 | -------------------------------------------------------------------------------- /docs/assets/split.js: -------------------------------------------------------------------------------- 1 | /*! Split.js - v1.3.5 */ 2 | // https://github.com/nathancahill/Split.js 3 | // Copyright (c) 2017 Nathan Cahill; Licensed MIT 4 | 5 | (function(global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' 7 | ? (module.exports = factory()) 8 | : typeof define === 'function' && define.amd 9 | ? define(factory) 10 | : (global.Split = factory()); 11 | })(this, function() { 12 | 'use strict'; 13 | // The programming goals of Split.js are to deliver readable, understandable and 14 | // maintainable code, while at the same time manually optimizing for tiny minified file size, 15 | // browser compatibility without additional requirements, graceful fallback (IE8 is supported) 16 | // and very few assumptions about the user's page layout. 17 | var global = window; 18 | var document = global.document; 19 | 20 | // Save a couple long function names that are used frequently. 21 | // This optimization saves around 400 bytes. 22 | var addEventListener = 'addEventListener'; 23 | var removeEventListener = 'removeEventListener'; 24 | var getBoundingClientRect = 'getBoundingClientRect'; 25 | var NOOP = function() { 26 | return false; 27 | }; 28 | 29 | // Figure out if we're in IE8 or not. IE8 will still render correctly, 30 | // but will be static instead of draggable. 31 | var isIE8 = global.attachEvent && !global[addEventListener]; 32 | 33 | // This library only needs two helper functions: 34 | // 35 | // The first determines which prefixes of CSS calc we need. 36 | // We only need to do this once on startup, when this anonymous function is called. 37 | // 38 | // Tests -webkit, -moz and -o prefixes. Modified from StackOverflow: 39 | // http://stackoverflow.com/questions/16625140/js-feature-detection-to-detect-the-usage-of-webkit-calc-over-calc/16625167#16625167 40 | var calc = 41 | ['', '-webkit-', '-moz-', '-o-'] 42 | .filter(function(prefix) { 43 | var el = document.createElement('div'); 44 | el.style.cssText = 'width:' + prefix + 'calc(9px)'; 45 | 46 | return !!el.style.length; 47 | }) 48 | .shift() + 'calc'; 49 | 50 | // The second helper function allows elements and string selectors to be used 51 | // interchangeably. In either case an element is returned. This allows us to 52 | // do `Split([elem1, elem2])` as well as `Split(['#id1', '#id2'])`. 53 | var elementOrSelector = function(el) { 54 | if (typeof el === 'string' || el instanceof String) { 55 | return document.querySelector(el); 56 | } 57 | 58 | return el; 59 | }; 60 | 61 | // The main function to initialize a split. Split.js thinks about each pair 62 | // of elements as an independant pair. Dragging the gutter between two elements 63 | // only changes the dimensions of elements in that pair. This is key to understanding 64 | // how the following functions operate, since each function is bound to a pair. 65 | // 66 | // A pair object is shaped like this: 67 | // 68 | // { 69 | // a: DOM element, 70 | // b: DOM element, 71 | // aMin: Number, 72 | // bMin: Number, 73 | // dragging: Boolean, 74 | // parent: DOM element, 75 | // isFirst: Boolean, 76 | // isLast: Boolean, 77 | // direction: 'horizontal' | 'vertical' 78 | // } 79 | // 80 | // The basic sequence: 81 | // 82 | // 1. Set defaults to something sane. `options` doesn't have to be passed at all. 83 | // 2. Initialize a bunch of strings based on the direction we're splitting. 84 | // A lot of the behavior in the rest of the library is paramatized down to 85 | // rely on CSS strings and classes. 86 | // 3. Define the dragging helper functions, and a few helpers to go with them. 87 | // 4. Loop through the elements while pairing them off. Every pair gets an 88 | // `pair` object, a gutter, and special isFirst/isLast properties. 89 | // 5. Actually size the pair elements, insert gutters and attach event listeners. 90 | var Split = function(ids, options) { 91 | if (options === void 0) options = {}; 92 | 93 | var dimension; 94 | var clientDimension; 95 | var clientAxis; 96 | var position; 97 | var paddingA; 98 | var paddingB; 99 | var elements; 100 | 101 | // All DOM elements in the split should have a common parent. We can grab 102 | // the first elements parent and hope users read the docs because the 103 | // behavior will be whacky otherwise. 104 | var parent = elementOrSelector(ids[0]).parentNode; 105 | var parentFlexDirection = global.getComputedStyle(parent).flexDirection; 106 | 107 | // Set default options.sizes to equal percentages of the parent element. 108 | var sizes = 109 | options.sizes || 110 | ids.map(function() { 111 | return 100 / ids.length; 112 | }); 113 | 114 | // Standardize minSize to an array if it isn't already. This allows minSize 115 | // to be passed as a number. 116 | var minSize = options.minSize !== undefined ? options.minSize : 100; 117 | var minSizes = Array.isArray(minSize) 118 | ? minSize 119 | : ids.map(function() { 120 | return minSize; 121 | }); 122 | var gutterSize = options.gutterSize !== undefined ? options.gutterSize : 10; 123 | var snapOffset = options.snapOffset !== undefined ? options.snapOffset : 30; 124 | var direction = options.direction || 'horizontal'; 125 | var cursor = 126 | options.cursor || 127 | (direction === 'horizontal' ? 'ew-resize' : 'ns-resize'); 128 | var gutter = 129 | options.gutter || 130 | function(i, gutterDirection) { 131 | var gut = document.createElement('div'); 132 | gut.className = 'gutter gutter-' + gutterDirection; 133 | return gut; 134 | }; 135 | var elementStyle = 136 | options.elementStyle || 137 | function(dim, size, gutSize) { 138 | var style = {}; 139 | 140 | if (typeof size !== 'string' && !(size instanceof String)) { 141 | if (!isIE8) { 142 | style[dim] = calc + '(' + size + '% - ' + gutSize + 'px)'; 143 | } else { 144 | style[dim] = size + '%'; 145 | } 146 | } else { 147 | style[dim] = size; 148 | } 149 | 150 | return style; 151 | }; 152 | var gutterStyle = 153 | options.gutterStyle || 154 | function(dim, gutSize) { 155 | return (obj = {}), (obj[dim] = gutSize + 'px'), obj; 156 | var obj; 157 | }; 158 | 159 | // 2. Initialize a bunch of strings based on the direction we're splitting. 160 | // A lot of the behavior in the rest of the library is paramatized down to 161 | // rely on CSS strings and classes. 162 | if (direction === 'horizontal') { 163 | dimension = 'width'; 164 | clientDimension = 'clientWidth'; 165 | clientAxis = 'clientX'; 166 | position = 'left'; 167 | paddingA = 'paddingLeft'; 168 | paddingB = 'paddingRight'; 169 | } else if (direction === 'vertical') { 170 | dimension = 'height'; 171 | clientDimension = 'clientHeight'; 172 | clientAxis = 'clientY'; 173 | position = 'top'; 174 | paddingA = 'paddingTop'; 175 | paddingB = 'paddingBottom'; 176 | } 177 | 178 | // 3. Define the dragging helper functions, and a few helpers to go with them. 179 | // Each helper is bound to a pair object that contains it's metadata. This 180 | // also makes it easy to store references to listeners that that will be 181 | // added and removed. 182 | // 183 | // Even though there are no other functions contained in them, aliasing 184 | // this to self saves 50 bytes or so since it's used so frequently. 185 | // 186 | // The pair object saves metadata like dragging state, position and 187 | // event listener references. 188 | 189 | function setElementSize(el, size, gutSize) { 190 | // Split.js allows setting sizes via numbers (ideally), or if you must, 191 | // by string, like '300px'. This is less than ideal, because it breaks 192 | // the fluid layout that `calc(% - px)` provides. You're on your own if you do that, 193 | // make sure you calculate the gutter size by hand. 194 | var style = elementStyle(dimension, size, gutSize); 195 | 196 | // eslint-disable-next-line no-param-reassign 197 | Object.keys(style).forEach(function(prop) { 198 | return (el.style[prop] = style[prop]); 199 | }); 200 | } 201 | 202 | function setGutterSize(gutterElement, gutSize) { 203 | var style = gutterStyle(dimension, gutSize); 204 | 205 | // eslint-disable-next-line no-param-reassign 206 | Object.keys(style).forEach(function(prop) { 207 | return (gutterElement.style[prop] = style[prop]); 208 | }); 209 | } 210 | 211 | // Actually adjust the size of elements `a` and `b` to `offset` while dragging. 212 | // calc is used to allow calc(percentage + gutterpx) on the whole split instance, 213 | // which allows the viewport to be resized without additional logic. 214 | // Element a's size is the same as offset. b's size is total size - a size. 215 | // Both sizes are calculated from the initial parent percentage, 216 | // then the gutter size is subtracted. 217 | function adjust(offset) { 218 | var a = elements[this.a]; 219 | var b = elements[this.b]; 220 | var percentage = a.size + b.size; 221 | 222 | a.size = offset / this.size * percentage; 223 | b.size = percentage - offset / this.size * percentage; 224 | 225 | setElementSize(a.element, a.size, this.aGutterSize); 226 | setElementSize(b.element, b.size, this.bGutterSize); 227 | } 228 | 229 | // drag, where all the magic happens. The logic is really quite simple: 230 | // 231 | // 1. Ignore if the pair is not dragging. 232 | // 2. Get the offset of the event. 233 | // 3. Snap offset to min if within snappable range (within min + snapOffset). 234 | // 4. Actually adjust each element in the pair to offset. 235 | // 236 | // --------------------------------------------------------------------- 237 | // | | <- a.minSize || b.minSize -> | | 238 | // | | | <- this.snapOffset || this.snapOffset -> | | | 239 | // | | | || | | | 240 | // | | | || | | | 241 | // --------------------------------------------------------------------- 242 | // | <- this.start this.size -> | 243 | function drag(e) { 244 | var offset; 245 | 246 | if (!this.dragging) { 247 | return; 248 | } 249 | 250 | // Get the offset of the event from the first side of the 251 | // pair `this.start`. Supports touch events, but not multitouch, so only the first 252 | // finger `touches[0]` is counted. 253 | if ('touches' in e) { 254 | offset = e.touches[0][clientAxis] - this.start; 255 | } else { 256 | offset = e[clientAxis] - this.start; 257 | } 258 | 259 | // If within snapOffset of min or max, set offset to min or max. 260 | // snapOffset buffers a.minSize and b.minSize, so logic is opposite for both. 261 | // Include the appropriate gutter sizes to prevent overflows. 262 | if (offset <= elements[this.a].minSize + snapOffset + this.aGutterSize) { 263 | offset = elements[this.a].minSize + this.aGutterSize; 264 | } else if ( 265 | offset >= 266 | this.size - (elements[this.b].minSize + snapOffset + this.bGutterSize) 267 | ) { 268 | offset = this.size - (elements[this.b].minSize + this.bGutterSize); 269 | } 270 | 271 | // Actually adjust the size. 272 | adjust.call(this, offset); 273 | 274 | // Call the drag callback continously. Don't do anything too intensive 275 | // in this callback. 276 | if (options.onDrag) { 277 | options.onDrag(); 278 | } 279 | } 280 | 281 | // Cache some important sizes when drag starts, so we don't have to do that 282 | // continously: 283 | // 284 | // `size`: The total size of the pair. First + second + first gutter + second gutter. 285 | // `start`: The leading side of the first element. 286 | // 287 | // ------------------------------------------------ 288 | // | aGutterSize -> ||| | 289 | // | ||| | 290 | // | ||| | 291 | // | ||| <- bGutterSize | 292 | // ------------------------------------------------ 293 | // | <- start size -> | 294 | function calculateSizes() { 295 | // Figure out the parent size minus padding. 296 | var a = elements[this.a].element; 297 | var b = elements[this.b].element; 298 | 299 | this.size = 300 | a[getBoundingClientRect]()[dimension] + 301 | b[getBoundingClientRect]()[dimension] + 302 | this.aGutterSize + 303 | this.bGutterSize; 304 | this.start = a[getBoundingClientRect]()[position]; 305 | } 306 | 307 | // stopDragging is very similar to startDragging in reverse. 308 | function stopDragging() { 309 | var self = this; 310 | var a = elements[self.a].element; 311 | var b = elements[self.b].element; 312 | 313 | if (self.dragging && options.onDragEnd) { 314 | options.onDragEnd(); 315 | } 316 | 317 | self.dragging = false; 318 | 319 | // Remove the stored event listeners. This is why we store them. 320 | global[removeEventListener]('mouseup', self.stop); 321 | global[removeEventListener]('touchend', self.stop); 322 | global[removeEventListener]('touchcancel', self.stop); 323 | 324 | self.parent[removeEventListener]('mousemove', self.move); 325 | self.parent[removeEventListener]('touchmove', self.move); 326 | 327 | // Delete them once they are removed. I think this makes a difference 328 | // in memory usage with a lot of splits on one page. But I don't know for sure. 329 | delete self.stop; 330 | delete self.move; 331 | 332 | a[removeEventListener]('selectstart', NOOP); 333 | a[removeEventListener]('dragstart', NOOP); 334 | b[removeEventListener]('selectstart', NOOP); 335 | b[removeEventListener]('dragstart', NOOP); 336 | 337 | a.style.userSelect = ''; 338 | a.style.webkitUserSelect = ''; 339 | a.style.MozUserSelect = ''; 340 | a.style.pointerEvents = ''; 341 | 342 | b.style.userSelect = ''; 343 | b.style.webkitUserSelect = ''; 344 | b.style.MozUserSelect = ''; 345 | b.style.pointerEvents = ''; 346 | 347 | self.gutter.style.cursor = ''; 348 | self.parent.style.cursor = ''; 349 | } 350 | 351 | // startDragging calls `calculateSizes` to store the inital size in the pair object. 352 | // It also adds event listeners for mouse/touch events, 353 | // and prevents selection while dragging so avoid the selecting text. 354 | function startDragging(e) { 355 | // Alias frequently used variables to save space. 200 bytes. 356 | var self = this; 357 | var a = elements[self.a].element; 358 | var b = elements[self.b].element; 359 | 360 | // Call the onDragStart callback. 361 | if (!self.dragging && options.onDragStart) { 362 | options.onDragStart(); 363 | } 364 | 365 | // Don't actually drag the element. We emulate that in the drag function. 366 | e.preventDefault(); 367 | 368 | // Set the dragging property of the pair object. 369 | self.dragging = true; 370 | 371 | // Create two event listeners bound to the same pair object and store 372 | // them in the pair object. 373 | self.move = drag.bind(self); 374 | self.stop = stopDragging.bind(self); 375 | 376 | // All the binding. `window` gets the stop events in case we drag out of the elements. 377 | global[addEventListener]('mouseup', self.stop); 378 | global[addEventListener]('touchend', self.stop); 379 | global[addEventListener]('touchcancel', self.stop); 380 | 381 | self.parent[addEventListener]('mousemove', self.move); 382 | self.parent[addEventListener]('touchmove', self.move); 383 | 384 | // Disable selection. Disable! 385 | a[addEventListener]('selectstart', NOOP); 386 | a[addEventListener]('dragstart', NOOP); 387 | b[addEventListener]('selectstart', NOOP); 388 | b[addEventListener]('dragstart', NOOP); 389 | 390 | a.style.userSelect = 'none'; 391 | a.style.webkitUserSelect = 'none'; 392 | a.style.MozUserSelect = 'none'; 393 | a.style.pointerEvents = 'none'; 394 | 395 | b.style.userSelect = 'none'; 396 | b.style.webkitUserSelect = 'none'; 397 | b.style.MozUserSelect = 'none'; 398 | b.style.pointerEvents = 'none'; 399 | 400 | // Set the cursor, both on the gutter and the parent element. 401 | // Doing only a, b and gutter causes flickering. 402 | self.gutter.style.cursor = cursor; 403 | self.parent.style.cursor = cursor; 404 | 405 | // Cache the initial sizes of the pair. 406 | calculateSizes.call(self); 407 | } 408 | 409 | // 5. Create pair and element objects. Each pair has an index reference to 410 | // elements `a` and `b` of the pair (first and second elements). 411 | // Loop through the elements while pairing them off. Every pair gets a 412 | // `pair` object, a gutter, and isFirst/isLast properties. 413 | // 414 | // Basic logic: 415 | // 416 | // - Starting with the second element `i > 0`, create `pair` objects with 417 | // `a = i - 1` and `b = i` 418 | // - Set gutter sizes based on the _pair_ being first/last. The first and last 419 | // pair have gutterSize / 2, since they only have one half gutter, and not two. 420 | // - Create gutter elements and add event listeners. 421 | // - Set the size of the elements, minus the gutter sizes. 422 | // 423 | // ----------------------------------------------------------------------- 424 | // | i=0 | i=1 | i=2 | i=3 | 425 | // | | isFirst | | isLast | 426 | // | pair 0 pair 1 pair 2 | 427 | // | | | | | 428 | // ----------------------------------------------------------------------- 429 | var pairs = []; 430 | elements = ids.map(function(id, i) { 431 | // Create the element object. 432 | var element = { 433 | element: elementOrSelector(id), 434 | size: sizes[i], 435 | minSize: minSizes[i] 436 | }; 437 | 438 | var pair; 439 | 440 | if (i > 0) { 441 | // Create the pair object with it's metadata. 442 | pair = { 443 | a: i - 1, 444 | b: i, 445 | dragging: false, 446 | isFirst: i === 1, 447 | isLast: i === ids.length - 1, 448 | direction: direction, 449 | parent: parent 450 | }; 451 | 452 | // For first and last pairs, first and last gutter width is half. 453 | pair.aGutterSize = gutterSize; 454 | pair.bGutterSize = gutterSize; 455 | 456 | if (pair.isFirst) { 457 | pair.aGutterSize = gutterSize / 2; 458 | } 459 | 460 | if (pair.isLast) { 461 | pair.bGutterSize = gutterSize / 2; 462 | } 463 | 464 | // if the parent has a reverse flex-direction, switch the pair elements. 465 | if ( 466 | parentFlexDirection === 'row-reverse' || 467 | parentFlexDirection === 'column-reverse' 468 | ) { 469 | var temp = pair.a; 470 | pair.a = pair.b; 471 | pair.b = temp; 472 | } 473 | } 474 | 475 | // Determine the size of the current element. IE8 is supported by 476 | // staticly assigning sizes without draggable gutters. Assigns a string 477 | // to `size`. 478 | // 479 | // IE9 and above 480 | if (!isIE8) { 481 | // Create gutter elements for each pair. 482 | if (i > 0) { 483 | var gutterElement = gutter(i, direction); 484 | setGutterSize(gutterElement, gutterSize); 485 | 486 | gutterElement[addEventListener]( 487 | 'mousedown', 488 | startDragging.bind(pair) 489 | ); 490 | gutterElement[addEventListener]( 491 | 'touchstart', 492 | startDragging.bind(pair) 493 | ); 494 | 495 | parent.insertBefore(gutterElement, element.element); 496 | 497 | pair.gutter = gutterElement; 498 | } 499 | } 500 | 501 | // Set the element size to our determined size. 502 | // Half-size gutters for first and last elements. 503 | if (i === 0 || i === ids.length - 1) { 504 | setElementSize(element.element, element.size, gutterSize / 2); 505 | } else { 506 | setElementSize(element.element, element.size, gutterSize); 507 | } 508 | 509 | var computedSize = element.element[getBoundingClientRect]()[dimension]; 510 | 511 | if (computedSize < element.minSize) { 512 | element.minSize = computedSize; 513 | } 514 | 515 | // After the first iteration, and we have a pair object, append it to the 516 | // list of pairs. 517 | if (i > 0) { 518 | pairs.push(pair); 519 | } 520 | 521 | return element; 522 | }); 523 | 524 | function setSizes(newSizes) { 525 | newSizes.forEach(function(newSize, i) { 526 | if (i > 0) { 527 | var pair = pairs[i - 1]; 528 | var a = elements[pair.a]; 529 | var b = elements[pair.b]; 530 | 531 | a.size = newSizes[i - 1]; 532 | b.size = newSize; 533 | 534 | setElementSize(a.element, a.size, pair.aGutterSize); 535 | setElementSize(b.element, b.size, pair.bGutterSize); 536 | } 537 | }); 538 | } 539 | 540 | function destroy() { 541 | pairs.forEach(function(pair) { 542 | pair.parent.removeChild(pair.gutter); 543 | elements[pair.a].element.style[dimension] = ''; 544 | elements[pair.b].element.style[dimension] = ''; 545 | }); 546 | } 547 | 548 | if (isIE8) { 549 | return { 550 | setSizes: setSizes, 551 | destroy: destroy 552 | }; 553 | } 554 | 555 | return { 556 | setSizes: setSizes, 557 | getSizes: function getSizes() { 558 | return elements.map(function(element) { 559 | return element.size; 560 | }); 561 | }, 562 | collapse: function collapse(i) { 563 | if (i === pairs.length) { 564 | var pair = pairs[i - 1]; 565 | 566 | calculateSizes.call(pair); 567 | 568 | if (!isIE8) { 569 | adjust.call(pair, pair.size - pair.bGutterSize); 570 | } 571 | } else { 572 | var pair$1 = pairs[i]; 573 | 574 | calculateSizes.call(pair$1); 575 | 576 | if (!isIE8) { 577 | adjust.call(pair$1, pair$1.aGutterSize); 578 | } 579 | } 580 | }, 581 | destroy: destroy 582 | }; 583 | }; 584 | 585 | return Split; 586 | }); 587 | -------------------------------------------------------------------------------- /docs/assets/style.css: -------------------------------------------------------------------------------- 1 | .documentation { 2 | font-family: Helvetica, sans-serif; 3 | color: #666; 4 | line-height: 1.5; 5 | background: #f5f5f5; 6 | } 7 | 8 | .black { 9 | color: #666; 10 | } 11 | 12 | .bg-white { 13 | background-color: #fff; 14 | } 15 | 16 | h4 { 17 | margin: 20px 0 10px 0; 18 | } 19 | 20 | .documentation h3 { 21 | color: #000; 22 | } 23 | 24 | .border-bottom { 25 | border-color: #ddd; 26 | } 27 | 28 | a { 29 | color: #1184CE; 30 | text-decoration: none; 31 | } 32 | 33 | .documentation a[href]:hover { 34 | text-decoration: underline; 35 | } 36 | 37 | a:hover { 38 | cursor: pointer; 39 | } 40 | 41 | .py1-ul li { 42 | padding: 5px 0; 43 | } 44 | 45 | .max-height-100 { 46 | max-height: 100%; 47 | } 48 | 49 | .height-viewport-100 { 50 | height: 100vh; 51 | } 52 | 53 | section:target h3 { 54 | font-weight:700; 55 | } 56 | 57 | .documentation td, 58 | .documentation th { 59 | padding: .25rem .25rem; 60 | } 61 | 62 | h1:hover .anchorjs-link, 63 | h2:hover .anchorjs-link, 64 | h3:hover .anchorjs-link, 65 | h4:hover .anchorjs-link { 66 | opacity: 1; 67 | } 68 | 69 | .fix-3 { 70 | width: 25%; 71 | max-width: 244px; 72 | } 73 | 74 | .fix-3 { 75 | width: 25%; 76 | max-width: 244px; 77 | } 78 | 79 | @media (min-width: 52em) { 80 | .fix-margin-3 { 81 | margin-left: 25%; 82 | } 83 | } 84 | 85 | .pre, pre, code, .code { 86 | font-family: Source Code Pro,Menlo,Consolas,Liberation Mono,monospace; 87 | font-size: 14px; 88 | } 89 | 90 | .fill-light { 91 | background: #F9F9F9; 92 | } 93 | 94 | .width2 { 95 | width: 1rem; 96 | } 97 | 98 | .input { 99 | font-family: inherit; 100 | display: block; 101 | width: 100%; 102 | height: 2rem; 103 | padding: .5rem; 104 | margin-bottom: 1rem; 105 | border: 1px solid #ccc; 106 | font-size: .875rem; 107 | border-radius: 3px; 108 | box-sizing: border-box; 109 | } 110 | 111 | table { 112 | border-collapse: collapse; 113 | } 114 | 115 | .prose table th, 116 | .prose table td { 117 | text-align: left; 118 | padding:8px; 119 | border:1px solid #ddd; 120 | } 121 | 122 | .prose table th:nth-child(1) { border-right: none; } 123 | .prose table th:nth-child(2) { border-left: none; } 124 | 125 | .prose table { 126 | border:1px solid #ddd; 127 | } 128 | 129 | .prose-big { 130 | font-size: 18px; 131 | line-height: 30px; 132 | } 133 | 134 | .quiet { 135 | opacity: 0.7; 136 | } 137 | 138 | .minishadow { 139 | box-shadow: 2px 2px 10px #f3f3f3; 140 | } 141 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ml-xgboost 1.1.2 | Documentation 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |

ml-xgboost

17 |
1.1.2
18 | 23 |
24 | 97 |
98 | 101 |
102 |
103 |
104 | 105 | 106 |
107 | 108 | 109 |
110 | 111 |

112 | constructor 113 |

114 | 115 | 116 | 117 | src/loadXGBoost.js 118 | 119 | 120 |
121 | 122 | 123 | 124 | 125 |
new constructor(options: object, model: object)
126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 |
Parameters
138 |
139 | 140 |
141 |
142 | options (object) 143 | Same parameters described 144 | here 145 | , Default parameters below. 146 | 147 |
148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 247 | 248 | 249 | 250 | 251 | 252 | 253 |
NameDescription
options.booster string 164 | 165 | (default 'gbtree') 166 |
options.objective string 174 | 175 | (default 'reg:linear') 176 |
options.max_depth number 184 | 185 | (default 5) 186 |
options.eta number 194 | 195 | (default 0.1) 196 |
options.min_child_weight number 204 | 205 | (default 1) 206 |
options.subsample number 214 | 215 | (default 0.5) 216 |
options.colsample_bytree number 224 | 225 | (default 1) 226 |
options.silent number 234 | 235 | (default 1) 236 |
options.iterations number 244 | 245 | (default 200) 246 |
254 | 255 |
256 | 257 |
258 |
259 | model (object) 260 | for load purposes. 261 | 262 |
263 | 264 |
265 | 266 |
267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 |
283 | 284 | 285 | 286 | 287 |
288 | 289 | 290 |
291 | 292 |

293 | free 294 |

295 | 296 | 297 | 298 | src/loadXGBoost.js 299 | 300 | 301 |
302 | 303 | 304 |

Free the memory allocated for the model. Since this memory is stored in the memory model of emscripten, 305 | it is allocated within an ArrayBuffer and WILL NOT BE GARBARGE COLLECTED, you have to explicitly free it. 306 | So not calling this will result in memory leaks. As of today in the browser, there is no way to hook the 307 | garbage collection of the XGBoost object to free it automatically. Free the memory that was created by the 308 | compiled XGBoost library to. store the model. This model is reused every time the predict method is called.

309 | 310 | 311 |
free()
312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 |
338 | 339 | 340 | 341 | 342 |
343 | 344 | 345 |
346 | 347 |

348 | predict 349 |

350 | 351 | 352 | 353 | src/loadXGBoost.js 354 | 355 | 356 |
357 | 358 | 359 |

Predicts the output given the matrix to predict.

360 | 361 | 362 |
predict(toPredict: (Matrix | Array<Array<number>>)): Array<number>
363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 |
Parameters
375 |
376 | 377 |
378 |
379 | toPredict ((Matrix | Array<Array<number>>)) 380 | 381 |
382 | 383 |
384 | 385 |
386 | 387 | 388 | 389 | 390 | 391 | 392 |
Returns
393 | Array<number>: 394 | predictions 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 |
410 | 411 | 412 | 413 | 414 |
415 | 416 | 417 |
418 | 419 |

420 | toJSON 421 |

422 | 423 | 424 | 425 | src/loadXGBoost.js 426 | 427 | 428 |
429 | 430 | 431 |

Export the current model to JSON.

432 | 433 | 434 |
toJSON(): object
435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 |
Returns
452 | object: 453 | Current model. 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 |
469 | 470 | 471 | 472 | 473 |
474 | 475 | 476 |
477 | 478 |

479 | train 480 |

481 | 482 | 483 | 484 | src/loadXGBoost.js 485 | 486 | 487 |
488 | 489 | 490 |

Train the decision tree with the given training set and labels.

491 | 492 | 493 |
train(trainingSet: (Matrix | Array<Array<number>>), trainingValues: Array<number>)
494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 |
Parameters
506 |
507 | 508 |
509 |
510 | trainingSet ((Matrix | Array<Array<number>>)) 511 | 512 |
513 | 514 |
515 | 516 |
517 |
518 | trainingValues (Array<number>) 519 | 520 |
521 | 522 |
523 | 524 |
525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 |
541 | 542 | 543 | 544 | 545 |
546 | 547 | 548 |
549 | 550 |

551 | load 552 |

553 | 554 | 555 | 556 | src/loadXGBoost.js 557 | 558 | 559 |
560 | 561 | 562 |

Load a Decision tree classifier with the given model.

563 | 564 | 565 |
load(model: object): XGBoost
566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 |
Parameters
578 |
579 | 580 |
581 |
582 | model (object) 583 | 584 |
585 | 586 |
587 | 588 |
589 | 590 | 591 | 592 | 593 | 594 | 595 |
Returns
596 | XGBoost: 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 |
613 | 614 | 615 | 616 | 617 |
618 | 619 | 620 |
621 | 622 |

623 | loadFromModel 624 |

625 | 626 | 627 | 628 | src/loadXGBoost.js 629 | 630 | 631 |
632 | 633 | 634 |

Load a model trained from other programming language

635 | 636 | 637 |
loadFromModel(filepath: string, options: object): XGBoost
638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 |
Parameters
650 |
651 | 652 |
653 |
654 | filepath (string) 655 | 656 |
657 | 658 |
659 | 660 |
661 |
662 | options (object 663 | = {}) 664 | 665 |
666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 683 | 687 | 688 | 689 | 690 | 691 | 692 |
NameDescription
options.labels Array? 682 | Some classifiers are trained with a one-hot encoder (Ex: Python API) so the 684 | current classifier returns the probability of each class, if you want the single predictions, you should provide 685 | an array with the corresponding labels, if you are doing regression you should ignore this option 686 |
693 | 694 |
695 | 696 |
697 | 698 | 699 | 700 | 701 | 702 | 703 |
Returns
704 | XGBoost: 705 | model 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 |
721 | 722 | 723 | 724 |
725 |
726 | 727 | 728 | 729 | 730 | 731 | -------------------------------------------------------------------------------- /js-interfaces.cpp: -------------------------------------------------------------------------------- 1 | #include "js-interfaces.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | Model create_model(float* dataset, float* labels, int rows, int cols) { 12 | BoosterHandle* model = new BoosterHandle(); 13 | DMatrixHandle* h_train = new DMatrixHandle(); 14 | XGDMatrixCreateFromMat(dataset, rows, cols, -1, h_train); 15 | XGDMatrixSetFloatInfo(*h_train, "label", labels, rows); 16 | XGBoosterCreate(h_train, 1, model); 17 | 18 | return new std::pair(model, h_train); 19 | } 20 | 21 | void set_param(Model model, char* arg, char* value) { 22 | XGBoosterSetParam(*(model->first), arg, value); 23 | } 24 | 25 | void train_full_model(Model model, int iterations) { 26 | for (int i = 0; i < iterations; ++i) { 27 | XGBoosterUpdateOneIter(*(model->first), i, *(model->second)); 28 | } 29 | } 30 | 31 | long prediction_size(Model model, float* dataset, int dimensions, const float** output) { 32 | DMatrixHandle h_test; 33 | XGDMatrixCreateFromMat(dataset, 1, dimensions, -1, &h_test); 34 | bst_ulong out_len; 35 | XGBoosterPredict(*(model->first), h_test, 0, 0, &out_len, output); 36 | XGDMatrixFree(h_test); 37 | return out_len; 38 | } 39 | 40 | long predict_one(Model model, float* dataset, int dimensions, float* prediction) { 41 | 42 | const float* output = nullptr; 43 | bst_ulong out_len = prediction_size(model, dataset, dimensions, &output); 44 | /* 45 | DMatrixHandle h_test; 46 | XGDMatrixCreateFromMat(dataset, 1, dimensions, -1, &h_test); 47 | bst_ulong out_len; 48 | const float* output; 49 | XGBoosterPredict(*(model->first), h_test, 0, 0, &out_len, &output);*/ 50 | 51 | for(bst_ulong i = 0; i < out_len; ++i) { 52 | prediction[i] = output[i]; 53 | } 54 | 55 | return static_cast(out_len); 56 | } 57 | 58 | void free_memory_model(Model model) { 59 | XGBoosterFree(*(model->first)); 60 | if((model->second) != nullptr) { 61 | XGDMatrixFree(*(model->second)); 62 | } 63 | delete model; 64 | } 65 | 66 | int save_model(Model model) { 67 | int success = XGBoosterSaveModel(*(model->first), "testfile.model"); 68 | if(success < 0) { 69 | return -1; 70 | } 71 | 72 | int size = 0; 73 | std::ifstream test("testfile.model", std::ifstream::binary); 74 | if(test) { 75 | std::filebuf* pbuf = test.rdbuf(); 76 | size = static_cast(pbuf->pubseekoff(0, test.end, test.in)); 77 | test.close(); 78 | } 79 | 80 | return size; 81 | } 82 | 83 | void get_file_content(char* buffer, int size) { 84 | std::unique_ptr fi(dmlc::Stream::Create("testfile.model", "r")); 85 | fi->Read(buffer, size); 86 | } 87 | 88 | Model load_model(char* serialized, int size) { 89 | std::unique_ptr fi(dmlc::Stream::Create("load.model", "w")); 90 | fi->Write(serialized, size); 91 | fi.reset(); 92 | 93 | BoosterHandle* loadModel = new BoosterHandle(); 94 | XGBoosterCreate(0, 0, loadModel); 95 | int success = XGBoosterLoadModel(*loadModel, "load.model"); 96 | if(success < 0) { 97 | return nullptr; 98 | } 99 | 100 | return new std::pair(loadModel, nullptr); 101 | } -------------------------------------------------------------------------------- /js-interfaces.h: -------------------------------------------------------------------------------- 1 | #ifndef XGBOOST_JS_JS_INTERFACES_H 2 | #define XGBOOST_JS_JS_INTERFACES_H 3 | 4 | #include "xgboost/include/xgboost/c_api.h" 5 | 6 | #include 7 | 8 | typedef std::pair* Model; 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | Model create_model(float* dataset, float* labels, int rows, int cols); 15 | void set_param(Model model, char* arg, char* value); 16 | void train_full_model(Model model, int iterations); 17 | long predict_one(Model model, float* dataset, int dimensions, float* prediction); 18 | long prediction_size(Model model, float* dataset, int dimensions, const float** output); 19 | void free_memory_model(Model model); 20 | int save_model(Model model); 21 | void get_file_content(char* buffer, int size); 22 | Model load_model(char* serialized, int size); 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | 28 | #endif //XGBOOST_JS_JS_INTERFACES_H 29 | -------------------------------------------------------------------------------- /make/minimum.mk: -------------------------------------------------------------------------------- 1 | #----------------------------------------------------- 2 | # xgboost: minumum dependency configuration, 3 | # see config.mk for template. 4 | #---------------------------------------------------- 5 | 6 | export CXX = em++ 7 | export CC = emcc 8 | 9 | # Whether enable openmp support, needed for multi-threading. 10 | USE_OPENMP = 0 11 | 12 | # whether use HDFS support during compile 13 | USE_HDFS = 0 14 | 15 | # whether use AWS S3 support during compile 16 | USE_S3 = 0 17 | 18 | # whether use Azure blob support during compile 19 | USE_AZURE = 0 20 | 21 | # Rabit library version, 22 | # - librabit.a Normal distributed version. 23 | # - librabit_empty.a Non distributed mock version, 24 | LIB_RABIT = librabit_empty.a 25 | 26 | -------------------------------------------------------------------------------- /models/generate_model.py: -------------------------------------------------------------------------------- 1 | import xgboost as xgb 2 | import numpy as np 3 | from sklearn.datasets import load_iris 4 | 5 | data = load_iris() 6 | X = data.data 7 | y = data.target 8 | 9 | clf = xgb.XGBClassifier(objective='multi:softmax') 10 | clf.fit(X, y) 11 | print(clf.predict(X)) 12 | 13 | clf._Booster.save_model('output.model') -------------------------------------------------------------------------------- /models/output.model: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mljs/xgboost/7766ea17ed7b42b9ae10746c95e26c3480724721/models/output.model -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ml-xgboost", 3 | "version": "1.1.2", 4 | "description": "", 5 | "main": "lib/index.js", 6 | "module": "src/index.js", 7 | "files": [ 8 | "lib", 9 | "src", 10 | "dist" 11 | ], 12 | "scripts": { 13 | "build": "rimraf dist && make clean && make", 14 | "eslint": "eslint src", 15 | "eslint-fix": "npm run eslint -- --fix", 16 | "prepublishOnly": "mkdir -p lib && cp ./dist/wasm/xgboost.wasm ./lib/ && rollup -c", 17 | "test": "run-s testonly eslint", 18 | "testonly": "jest" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/mljs/xgboost.git" 23 | }, 24 | "keywords": [], 25 | "author": "Jefferson Javier Hernández Panqueba", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/mljs/xgboost/issues" 29 | }, 30 | "homepage": "https://github.com/mljs/xgboost#readme", 31 | "jest": { 32 | "testEnvironment": "node" 33 | }, 34 | "devDependencies": { 35 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", 36 | "eslint": "^4.16.0", 37 | "eslint-config-cheminfo": "^1.14.1", 38 | "eslint-plugin-import": "^2.8.0", 39 | "eslint-plugin-jest": "^21.7.0", 40 | "eslint-plugin-no-only-tests": "^2.0.0", 41 | "jest": "^21.2.1", 42 | "ml-confusion-matrix": "^0.3.0", 43 | "ml-dataset-iris": "^1.0.0", 44 | "npm-run-all": "^4.1.2", 45 | "rollup": "^0.49.3" 46 | }, 47 | "dependencies": { 48 | "ml-matrix": "^5.0.1" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /replace-files/dmlc-core/base.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright (c) 2015 by Contributors 3 | * \file base.h 4 | * \brief defines configuration macros 5 | */ 6 | #ifndef DMLC_BASE_H_ 7 | #define DMLC_BASE_H_ 8 | 9 | /*! \brief whether use glog for logging */ 10 | #ifndef DMLC_USE_GLOG 11 | #define DMLC_USE_GLOG 0 12 | #endif 13 | 14 | /*! 15 | * \brief whether throw dmlc::Error instead of 16 | * directly calling abort when FATAL error occured 17 | * NOTE: this may still not be perfect. 18 | * do not use FATAL and CHECK in destructors 19 | */ 20 | #ifndef DMLC_LOG_FATAL_THROW 21 | #define DMLC_LOG_FATAL_THROW 1 22 | #endif 23 | 24 | /*! 25 | * \brief whether always log a message before throw 26 | * This can help identify the error that cannot be catched. 27 | */ 28 | #ifndef DMLC_LOG_BEFORE_THROW 29 | #define DMLC_LOG_BEFORE_THROW 1 30 | #endif 31 | 32 | /*! 33 | * \brief Whether to use customized logger, 34 | * whose output can be decided by other libraries. 35 | */ 36 | #ifndef DMLC_LOG_CUSTOMIZE 37 | #define DMLC_LOG_CUSTOMIZE 0 38 | #endif 39 | 40 | /*! 41 | * \brief Wheter to print stack trace for fatal error, 42 | * enabled on linux when using gcc. 43 | */ 44 | #if (!defined(DMLC_LOG_STACK_TRACE) && defined(__GNUC__) && !defined(__MINGW32__)) 45 | #define DMLC_LOG_STACK_TRACE 1 46 | #undef DMLC_LOG_STACK_TRACE 47 | #endif 48 | 49 | /*! \brief whether compile with hdfs support */ 50 | #ifndef DMLC_USE_HDFS 51 | #define DMLC_USE_HDFS 0 52 | #endif 53 | 54 | /*! \brief whether compile with s3 support */ 55 | #ifndef DMLC_USE_S3 56 | #define DMLC_USE_S3 0 57 | #endif 58 | 59 | /*! \brief whether or not use parameter server */ 60 | #ifndef DMLC_USE_PS 61 | #define DMLC_USE_PS 0 62 | #endif 63 | 64 | /*! \brief whether or not use c++11 support */ 65 | #ifndef DMLC_USE_CXX11 66 | #if defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(_MSC_VER) 67 | #define DMLC_USE_CXX11 1 68 | #else 69 | #define DMLC_USE_CXX11 (__cplusplus >= 201103L) 70 | #endif 71 | #endif 72 | 73 | /*! \brief strict CXX11 support */ 74 | #ifndef DMLC_STRICT_CXX11 75 | #if defined(_MSC_VER) 76 | #define DMLC_STRICT_CXX11 1 77 | #else 78 | #define DMLC_STRICT_CXX11 (__cplusplus >= 201103L) 79 | #endif 80 | #endif 81 | 82 | /*! \brief Whether cxx11 thread local is supported */ 83 | #ifndef DMLC_CXX11_THREAD_LOCAL 84 | #if defined(_MSC_VER) 85 | #if (_MSC_VER >= 1900) 86 | #define DMLC_CXX11_THREAD_LOCAL 1 87 | #else 88 | #define DMLC_CXX11_THREAD_LOCAL 0 89 | #endif 90 | #else 91 | #define DMLC_CXX11_THREAD_LOCAL (__cplusplus >= 201103L) 92 | #endif 93 | #endif 94 | 95 | 96 | /*! \brief whether RTTI is enabled */ 97 | #ifndef DMLC_ENABLE_RTTI 98 | #define DMLC_ENABLE_RTTI 1 99 | #endif 100 | 101 | /// check if g++ is before 4.6 102 | #if DMLC_USE_CXX11 && defined(__GNUC__) && !defined(__clang_version__) 103 | #if __GNUC__ == 4 && __GNUC_MINOR__ < 6 104 | #pragma message("Will need g++-4.6 or higher to compile all" \ 105 | "the features in dmlc-core, " \ 106 | "compile without c++0x, some features may be disabled") 107 | #undef DMLC_USE_CXX11 108 | #define DMLC_USE_CXX11 0 109 | #endif 110 | #endif 111 | 112 | 113 | /*! 114 | * \brief Enable std::thread related modules, 115 | * Used to disable some module in mingw compile. 116 | */ 117 | #ifndef DMLC_ENABLE_STD_THREAD 118 | #define DMLC_ENABLE_STD_THREAD DMLC_USE_CXX11 119 | #endif 120 | 121 | /*! \brief whether enable regex support, actually need g++-4.9 or higher*/ 122 | #ifndef DMLC_USE_REGEX 123 | #define DMLC_USE_REGEX DMLC_STRICT_CXX11 124 | #endif 125 | 126 | /*! \brief helper macro to supress unused warning */ 127 | #if defined(__GNUC__) 128 | #define DMLC_ATTRIBUTE_UNUSED __attribute__((unused)) 129 | #else 130 | #define DMLC_ATTRIBUTE_UNUSED 131 | #endif 132 | 133 | /*! \brief helper macro to generate string concat */ 134 | #define DMLC_STR_CONCAT_(__x, __y) __x##__y 135 | #define DMLC_STR_CONCAT(__x, __y) DMLC_STR_CONCAT_(__x, __y) 136 | 137 | /*! 138 | * \brief Disable copy constructor and assignment operator. 139 | * 140 | * If C++11 is supported, both copy and move constructors and 141 | * assignment operators are deleted explicitly. Otherwise, they are 142 | * only declared but not implemented. Place this macro in private 143 | * section if C++11 is not available. 144 | */ 145 | #ifndef DISALLOW_COPY_AND_ASSIGN 146 | # if DMLC_USE_CXX11 147 | # define DISALLOW_COPY_AND_ASSIGN(T) \ 148 | T(T const&) = delete; \ 149 | T(T&&) = delete; \ 150 | T& operator=(T const&) = delete; \ 151 | T& operator=(T&&) = delete 152 | # else 153 | # define DISALLOW_COPY_AND_ASSIGN(T) \ 154 | T(T const&); \ 155 | T& operator=(T const&) 156 | # endif 157 | #endif 158 | 159 | /// 160 | /// code block to handle optionally loading 161 | /// 162 | #if !defined(__GNUC__) 163 | #define fopen64 std::fopen 164 | #endif 165 | #if (defined __MINGW32__) && !(defined __MINGW64__) 166 | #define fopen64 std::fopen 167 | #endif 168 | #ifdef _MSC_VER 169 | #if _MSC_VER < 1900 170 | // NOTE: sprintf_s is not equivalent to snprintf, 171 | // they are equivalent when success, which is sufficient for our case 172 | #define snprintf sprintf_s 173 | #define vsnprintf vsprintf_s 174 | #endif 175 | #else 176 | #ifdef _FILE_OFFSET_BITS 177 | #if _FILE_OFFSET_BITS == 32 178 | #pragma message("Warning: FILE OFFSET BITS defined to be 32 bit") 179 | #endif 180 | #endif 181 | 182 | #ifdef __APPLE__ 183 | #define off64_t off_t 184 | #define fopen64 std::fopen 185 | #endif 186 | 187 | extern "C" { 188 | #include 189 | } 190 | #endif 191 | 192 | #ifdef _MSC_VER 193 | //! \cond Doxygen_Suppress 194 | typedef signed char int8_t; 195 | typedef __int16 int16_t; 196 | typedef __int32 int32_t; 197 | typedef __int64 int64_t; 198 | typedef unsigned char uint8_t; 199 | typedef unsigned __int16 uint16_t; 200 | typedef unsigned __int32 uint32_t; 201 | typedef unsigned __int64 uint64_t; 202 | //! \endcond 203 | #else 204 | #include 205 | #endif 206 | #include 207 | #include 208 | 209 | #if defined(_MSC_VER) && _MSC_VER < 1900 210 | #define noexcept_true throw () 211 | #define noexcept_false 212 | #define noexcept(a) noexcept_##a 213 | #endif 214 | 215 | #if DMLC_USE_CXX11 216 | #define DMLC_THROW_EXCEPTION noexcept(false) 217 | #define DMLC_NO_EXCEPTION noexcept(true) 218 | #else 219 | #define DMLC_THROW_EXCEPTION 220 | #define DMLC_NO_EXCEPTION 221 | #endif 222 | 223 | /*! \brief namespace for dmlc */ 224 | namespace dmlc { 225 | /*! 226 | * \brief safely get the beginning address of a vector 227 | * \param vec input vector 228 | * \return beginning address of a vector 229 | */ 230 | template 231 | inline T *BeginPtr(std::vector &vec) { // NOLINT(*) 232 | if (vec.size() == 0) { 233 | return NULL; 234 | } else { 235 | return &vec[0]; 236 | } 237 | } 238 | /*! 239 | * \brief get the beginning address of a const vector 240 | * \param vec input vector 241 | * \return beginning address of a vector 242 | */ 243 | template 244 | inline const T *BeginPtr(const std::vector &vec) { 245 | if (vec.size() == 0) { 246 | return NULL; 247 | } else { 248 | return &vec[0]; 249 | } 250 | } 251 | /*! 252 | * \brief get the beginning address of a string 253 | * \param str input string 254 | * \return beginning address of a string 255 | */ 256 | inline char* BeginPtr(std::string &str) { // NOLINT(*) 257 | if (str.length() == 0) return NULL; 258 | return &str[0]; 259 | } 260 | /*! 261 | * \brief get the beginning address of a const string 262 | * \param str input string 263 | * \return beginning address of a string 264 | */ 265 | inline const char* BeginPtr(const std::string &str) { 266 | if (str.length() == 0) return NULL; 267 | return &str[0]; 268 | } 269 | } // namespace dmlc 270 | 271 | #if defined(_MSC_VER) && _MSC_VER < 1900 272 | #define constexpr const 273 | #define alignof __alignof 274 | #endif 275 | 276 | #endif // DMLC_BASE_H_ 277 | -------------------------------------------------------------------------------- /replace-files/rabit/base.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright (c) 2015 by Contributors 3 | * \file base.h 4 | * \brief defines configuration macros 5 | */ 6 | #ifndef DMLC_BASE_H_ 7 | #define DMLC_BASE_H_ 8 | 9 | /*! \brief whether use glog for logging */ 10 | #ifndef DMLC_USE_GLOG 11 | #define DMLC_USE_GLOG 0 12 | #endif 13 | 14 | /*! 15 | * \brief whether throw dmlc::Error instead of 16 | * directly calling abort when FATAL error occured 17 | * NOTE: this may still not be perfect. 18 | * do not use FATAL and CHECK in destructors 19 | */ 20 | #ifndef DMLC_LOG_FATAL_THROW 21 | #define DMLC_LOG_FATAL_THROW 1 22 | #endif 23 | 24 | /*! 25 | * \brief whether always log a message before throw 26 | * This can help identify the error that cannot be catched. 27 | */ 28 | #ifndef DMLC_LOG_BEFORE_THROW 29 | #define DMLC_LOG_BEFORE_THROW 1 30 | #endif 31 | 32 | /*! 33 | * \brief Whether to use customized logger, 34 | * whose output can be decided by other libraries. 35 | */ 36 | #ifndef DMLC_LOG_CUSTOMIZE 37 | #define DMLC_LOG_CUSTOMIZE 0 38 | #endif 39 | 40 | /*! 41 | * \brief Wheter to print stack trace for fatal error, 42 | * enabled on linux when using gcc. 43 | */ 44 | #if (!defined(DMLC_LOG_STACK_TRACE) && defined(__GNUC__) && !defined(__MINGW32__)) 45 | #define DMLC_LOG_STACK_TRACE 1 46 | #undef DMLC_LOG_STACK_TRACE 47 | #endif 48 | 49 | /*! \brief whether compile with hdfs support */ 50 | #ifndef DMLC_USE_HDFS 51 | #define DMLC_USE_HDFS 0 52 | #endif 53 | 54 | /*! \brief whether compile with s3 support */ 55 | #ifndef DMLC_USE_S3 56 | #define DMLC_USE_S3 0 57 | #endif 58 | 59 | /*! \brief whether or not use parameter server */ 60 | #ifndef DMLC_USE_PS 61 | #define DMLC_USE_PS 0 62 | #endif 63 | 64 | /*! \brief whether or not use c++11 support */ 65 | #ifndef DMLC_USE_CXX11 66 | #if defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(_MSC_VER) 67 | #define DMLC_USE_CXX11 1 68 | #else 69 | #define DMLC_USE_CXX11 (__cplusplus >= 201103L) 70 | #endif 71 | #endif 72 | 73 | /*! \brief strict CXX11 support */ 74 | #ifndef DMLC_STRICT_CXX11 75 | #if defined(_MSC_VER) 76 | #define DMLC_STRICT_CXX11 1 77 | #else 78 | #define DMLC_STRICT_CXX11 (__cplusplus >= 201103L) 79 | #endif 80 | #endif 81 | 82 | /*! \brief Whether cxx11 thread local is supported */ 83 | #ifndef DMLC_CXX11_THREAD_LOCAL 84 | #if defined(_MSC_VER) 85 | #if (_MSC_VER >= 1900) 86 | #define DMLC_CXX11_THREAD_LOCAL 1 87 | #else 88 | #define DMLC_CXX11_THREAD_LOCAL 0 89 | #endif 90 | #else 91 | #define DMLC_CXX11_THREAD_LOCAL (__cplusplus >= 201103L) 92 | #endif 93 | #endif 94 | 95 | 96 | /*! \brief whether RTTI is enabled */ 97 | #ifndef DMLC_ENABLE_RTTI 98 | #define DMLC_ENABLE_RTTI 1 99 | #endif 100 | 101 | /// check if g++ is before 4.6 102 | #if DMLC_USE_CXX11 && defined(__GNUC__) && !defined(__clang_version__) 103 | #if __GNUC__ == 4 && __GNUC_MINOR__ < 6 104 | #pragma message("Will need g++-4.6 or higher to compile all" \ 105 | "the features in dmlc-core, " \ 106 | "compile without c++0x, some features may be disabled") 107 | #undef DMLC_USE_CXX11 108 | #define DMLC_USE_CXX11 0 109 | #endif 110 | #endif 111 | 112 | 113 | /*! 114 | * \brief Enable std::thread related modules, 115 | * Used to disable some module in mingw compile. 116 | */ 117 | #ifndef DMLC_ENABLE_STD_THREAD 118 | #define DMLC_ENABLE_STD_THREAD DMLC_USE_CXX11 119 | #endif 120 | 121 | /*! \brief whether enable regex support, actually need g++-4.9 or higher*/ 122 | #ifndef DMLC_USE_REGEX 123 | #define DMLC_USE_REGEX DMLC_STRICT_CXX11 124 | #endif 125 | 126 | /*! \brief helper macro to supress unused warning */ 127 | #if defined(__GNUC__) 128 | #define DMLC_ATTRIBUTE_UNUSED __attribute__((unused)) 129 | #else 130 | #define DMLC_ATTRIBUTE_UNUSED 131 | #endif 132 | 133 | /*! \brief helper macro to generate string concat */ 134 | #define DMLC_STR_CONCAT_(__x, __y) __x##__y 135 | #define DMLC_STR_CONCAT(__x, __y) DMLC_STR_CONCAT_(__x, __y) 136 | 137 | /*! 138 | * \brief Disable copy constructor and assignment operator. 139 | * 140 | * If C++11 is supported, both copy and move constructors and 141 | * assignment operators are deleted explicitly. Otherwise, they are 142 | * only declared but not implemented. Place this macro in private 143 | * section if C++11 is not available. 144 | */ 145 | #ifndef DISALLOW_COPY_AND_ASSIGN 146 | # if DMLC_USE_CXX11 147 | # define DISALLOW_COPY_AND_ASSIGN(T) \ 148 | T(T const&) = delete; \ 149 | T(T&&) = delete; \ 150 | T& operator=(T const&) = delete; \ 151 | T& operator=(T&&) = delete 152 | # else 153 | # define DISALLOW_COPY_AND_ASSIGN(T) \ 154 | T(T const&); \ 155 | T& operator=(T const&) 156 | # endif 157 | #endif 158 | 159 | /// 160 | /// code block to handle optionally loading 161 | /// 162 | #if !defined(__GNUC__) 163 | #define fopen64 std::fopen 164 | #endif 165 | #if (defined __MINGW32__) && !(defined __MINGW64__) 166 | #define fopen64 std::fopen 167 | #endif 168 | #ifdef _MSC_VER 169 | #if _MSC_VER < 1900 170 | // NOTE: sprintf_s is not equivalent to snprintf, 171 | // they are equivalent when success, which is sufficient for our case 172 | #define snprintf sprintf_s 173 | #define vsnprintf vsprintf_s 174 | #endif 175 | #else 176 | #ifdef _FILE_OFFSET_BITS 177 | #if _FILE_OFFSET_BITS == 32 178 | #pragma message("Warning: FILE OFFSET BITS defined to be 32 bit") 179 | #endif 180 | #endif 181 | 182 | #ifdef __APPLE__ 183 | #define off64_t off_t 184 | #define fopen64 std::fopen 185 | #endif 186 | 187 | extern "C" { 188 | #include 189 | } 190 | #endif 191 | 192 | #ifdef _MSC_VER 193 | //! \cond Doxygen_Suppress 194 | typedef signed char int8_t; 195 | typedef __int16 int16_t; 196 | typedef __int32 int32_t; 197 | typedef __int64 int64_t; 198 | typedef unsigned char uint8_t; 199 | typedef unsigned __int16 uint16_t; 200 | typedef unsigned __int32 uint32_t; 201 | typedef unsigned __int64 uint64_t; 202 | //! \endcond 203 | #else 204 | #include 205 | #endif 206 | #include 207 | #include 208 | 209 | #if defined(_MSC_VER) && _MSC_VER < 1900 210 | #define noexcept_true throw () 211 | #define noexcept_false 212 | #define noexcept(a) noexcept_##a 213 | #endif 214 | 215 | #if DMLC_USE_CXX11 216 | #define DMLC_THROW_EXCEPTION noexcept(false) 217 | #define DMLC_NO_EXCEPTION noexcept(true) 218 | #else 219 | #define DMLC_THROW_EXCEPTION 220 | #define DMLC_NO_EXCEPTION 221 | #endif 222 | 223 | /*! \brief namespace for dmlc */ 224 | namespace dmlc { 225 | /*! 226 | * \brief safely get the beginning address of a vector 227 | * \param vec input vector 228 | * \return beginning address of a vector 229 | */ 230 | template 231 | inline T *BeginPtr(std::vector &vec) { // NOLINT(*) 232 | if (vec.size() == 0) { 233 | return NULL; 234 | } else { 235 | return &vec[0]; 236 | } 237 | } 238 | /*! 239 | * \brief get the beginning address of a const vector 240 | * \param vec input vector 241 | * \return beginning address of a vector 242 | */ 243 | template 244 | inline const T *BeginPtr(const std::vector &vec) { 245 | if (vec.size() == 0) { 246 | return NULL; 247 | } else { 248 | return &vec[0]; 249 | } 250 | } 251 | /*! 252 | * \brief get the beginning address of a string 253 | * \param str input string 254 | * \return beginning address of a string 255 | */ 256 | inline char* BeginPtr(std::string &str) { // NOLINT(*) 257 | if (str.length() == 0) return NULL; 258 | return &str[0]; 259 | } 260 | /*! 261 | * \brief get the beginning address of a const string 262 | * \param str input string 263 | * \return beginning address of a string 264 | */ 265 | inline const char* BeginPtr(const std::string &str) { 266 | if (str.length() == 0) return NULL; 267 | return &str[0]; 268 | } 269 | } // namespace dmlc 270 | 271 | #if defined(_MSC_VER) && _MSC_VER < 1900 272 | #define constexpr const 273 | #define alignof __alignof 274 | #endif 275 | 276 | #endif // DMLC_BASE_H_ 277 | -------------------------------------------------------------------------------- /replace-files/xgboost/c_api.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright (c) 2015 by Contributors 3 | * \file c_api.h 4 | * \author Tianqi Chen 5 | * \brief C API of XGBoost, used for interfacing to other languages. 6 | */ 7 | #ifndef XGBOOST_C_API_H_ 8 | #define XGBOOST_C_API_H_ 9 | #include 10 | 11 | #ifdef __cplusplus 12 | #define XGB_EXTERN_C extern "C" 13 | #include 14 | #else 15 | #define XGB_EXTERN_C 16 | #include 17 | #include 18 | #endif 19 | 20 | // XGBoost C API will include APIs in Rabit C API 21 | #include 22 | 23 | #if defined(_MSC_VER) || defined(_WIN32) 24 | #define XGB_DLL XGB_EXTERN_C __declspec(dllexport) 25 | #else 26 | #define XGB_DLL XGB_EXTERN_C 27 | #endif 28 | 29 | // manually define unsigned long 30 | typedef uint64_t bst_ulong; // NOLINT(*) 31 | 32 | 33 | /*! \brief handle to DMatrix */ 34 | typedef void *DMatrixHandle; 35 | /*! \brief handle to Booster */ 36 | typedef void *BoosterHandle; 37 | /*! \brief handle to a data iterator */ 38 | typedef void *DataIterHandle; 39 | /*! \brief handle to a internal data holder. */ 40 | typedef void *DataHolderHandle; 41 | 42 | /*! \brief Mini batch used in XGBoost Data Iteration */ 43 | typedef struct { 44 | /*! \brief number of rows in the minibatch */ 45 | size_t size; 46 | /*! \brief row pointer to the rows in the data */ 47 | #ifdef __APPLE__ 48 | /* Necessary as Java on MacOS defines jlong as long int 49 | * and gcc defines int64_t as long long int. */ 50 | long* offset; // NOLINT(*) 51 | #else 52 | int64_t* offset; // NOLINT(*) 53 | #endif 54 | /*! \brief labels of each instance */ 55 | float* label; 56 | /*! \brief weight of each instance, can be NULL */ 57 | float* weight; 58 | /*! \brief feature index */ 59 | int* index; 60 | /*! \brief feature values */ 61 | float* value; 62 | } XGBoostBatchCSR; 63 | 64 | 65 | /*! 66 | * \brief Callback to set the data to handle, 67 | * \param handle The handle to the callback. 68 | * \param batch The data content to be set. 69 | */ 70 | XGB_EXTERN_C typedef int XGBCallbackSetData( 71 | DataHolderHandle handle, XGBoostBatchCSR batch); 72 | 73 | /*! 74 | * \brief The data reading callback function. 75 | * The iterator will be able to give subset of batch in the data. 76 | * 77 | * If there is data, the function will call set_function to set the data. 78 | * 79 | * \param data_handle The handle to the callback. 80 | * \param set_function The batch returned by the iterator 81 | * \param set_function_handle The handle to be passed to set function. 82 | * \return 0 if we are reaching the end and batch is not returned. 83 | */ 84 | XGB_EXTERN_C typedef int XGBCallbackDataIterNext( 85 | DataIterHandle data_handle, 86 | XGBCallbackSetData* set_function, 87 | DataHolderHandle set_function_handle); 88 | 89 | /*! 90 | * \brief get string message of the last error 91 | * 92 | * all function in this file will return 0 when success 93 | * and -1 when an error occurred, 94 | * XGBGetLastError can be called to retrieve the error 95 | * 96 | * this function is thread safe and can be called by different thread 97 | * \return const char* error information 98 | */ 99 | XGB_DLL const char *XGBGetLastError(); 100 | 101 | /*! 102 | * \brief load a data matrix 103 | * \param fname the name of the file 104 | * \param silent whether print messages during loading 105 | * \param out a loaded data matrix 106 | * \return 0 when success, -1 when failure happens 107 | */ 108 | XGB_DLL int XGDMatrixCreateFromFile(const char *fname, 109 | int silent, 110 | DMatrixHandle *out); 111 | 112 | /*! 113 | * \brief Create a DMatrix from a data iterator. 114 | * \param data_handle The handle to the data. 115 | * \param callback The callback to get the data. 116 | * \param cache_info Additional information about cache file, can be null. 117 | * \param out The created DMatrix 118 | * \return 0 when success, -1 when failure happens. 119 | */ 120 | XGB_DLL int XGDMatrixCreateFromDataIter( 121 | DataIterHandle data_handle, 122 | XGBCallbackDataIterNext* callback, 123 | const char* cache_info, 124 | DMatrixHandle *out); 125 | 126 | /*! 127 | * \brief create a matrix content from CSR format 128 | * \param indptr pointer to row headers 129 | * \param indices findex 130 | * \param data fvalue 131 | * \param nindptr number of rows in the matrix + 1 132 | * \param nelem number of nonzero elements in the matrix 133 | * \param num_col number of columns; when it's set to 0, then guess from data 134 | * \param out created dmatrix 135 | * \return 0 when success, -1 when failure happens 136 | */ 137 | XGB_DLL int XGDMatrixCreateFromCSREx(const size_t* indptr, 138 | const unsigned* indices, 139 | const float* data, 140 | size_t nindptr, 141 | size_t nelem, 142 | size_t num_col, 143 | DMatrixHandle* out); 144 | /*! 145 | * \deprecated 146 | * \brief create a matrix content from CSR format 147 | * \param indptr pointer to row headers 148 | * \param indices findex 149 | * \param data fvalue 150 | * \param nindptr number of rows in the matrix + 1 151 | * \param nelem number of nonzero elements in the matrix 152 | * \param out created dmatrix 153 | * \return 0 when success, -1 when failure happens 154 | */ 155 | XGB_DLL int XGDMatrixCreateFromCSR(const bst_ulong *indptr, 156 | const unsigned *indices, 157 | const float *data, 158 | bst_ulong nindptr, 159 | bst_ulong nelem, 160 | DMatrixHandle *out); 161 | /*! 162 | * \brief create a matrix content from CSC format 163 | * \param col_ptr pointer to col headers 164 | * \param indices findex 165 | * \param data fvalue 166 | * \param nindptr number of rows in the matrix + 1 167 | * \param nelem number of nonzero elements in the matrix 168 | * \param num_row number of rows; when it's set to 0, then guess from data 169 | * \param out created dmatrix 170 | * \return 0 when success, -1 when failure happens 171 | */ 172 | XGB_DLL int XGDMatrixCreateFromCSCEx(const size_t* col_ptr, 173 | const unsigned* indices, 174 | const float* data, 175 | size_t nindptr, 176 | size_t nelem, 177 | size_t num_row, 178 | DMatrixHandle* out); 179 | /*! 180 | * \deprecated 181 | * \brief create a matrix content from CSC format 182 | * \param col_ptr pointer to col headers 183 | * \param indices findex 184 | * \param data fvalue 185 | * \param nindptr number of rows in the matrix + 1 186 | * \param nelem number of nonzero elements in the matrix 187 | * \param out created dmatrix 188 | * \return 0 when success, -1 when failure happens 189 | */ 190 | XGB_DLL int XGDMatrixCreateFromCSC(const bst_ulong *col_ptr, 191 | const unsigned *indices, 192 | const float *data, 193 | bst_ulong nindptr, 194 | bst_ulong nelem, 195 | DMatrixHandle *out); 196 | /*! 197 | * \brief create matrix content from dense matrix 198 | * \param data pointer to the data space 199 | * \param nrow number of rows 200 | * \param ncol number columns 201 | * \param missing which value to represent missing value 202 | * \param out created dmatrix 203 | * \return 0 when success, -1 when failure happens 204 | */ 205 | XGB_DLL int XGDMatrixCreateFromMat(const float *data, 206 | bst_ulong nrow, 207 | bst_ulong ncol, 208 | float missing, 209 | DMatrixHandle *out); 210 | /*! 211 | * \brief create matrix content from dense matrix 212 | * \param data pointer to the data space 213 | * \param nrow number of rows 214 | * \param ncol number columns 215 | * \param missing which value to represent missing value 216 | * \param out created dmatrix 217 | * \param nthread number of threads (up to maximum cores available, if <=0 use all cores) 218 | * \return 0 when success, -1 when failure happens 219 | */ 220 | XGB_DLL int XGDMatrixCreateFromMat_omp(const float *data, 221 | bst_ulong nrow, 222 | bst_ulong ncol, 223 | float missing, 224 | DMatrixHandle *out, 225 | int nthread); 226 | /*! 227 | * \brief create a new dmatrix from sliced content of existing matrix 228 | * \param handle instance of data matrix to be sliced 229 | * \param idxset index set 230 | * \param len length of index set 231 | * \param out a sliced new matrix 232 | * \return 0 when success, -1 when failure happens 233 | */ 234 | XGB_DLL int XGDMatrixSliceDMatrix(DMatrixHandle handle, 235 | const int *idxset, 236 | bst_ulong len, 237 | DMatrixHandle *out); 238 | /*! 239 | * \brief free space in data matrix 240 | * \return 0 when success, -1 when failure happens 241 | */ 242 | XGB_DLL int XGDMatrixFree(DMatrixHandle handle); 243 | /*! 244 | * \brief load a data matrix into binary file 245 | * \param handle a instance of data matrix 246 | * \param fname file name 247 | * \param silent print statistics when saving 248 | * \return 0 when success, -1 when failure happens 249 | */ 250 | XGB_DLL int XGDMatrixSaveBinary(DMatrixHandle handle, 251 | const char *fname, int silent); 252 | /*! 253 | * \brief set float vector to a content in info 254 | * \param handle a instance of data matrix 255 | * \param field field name, can be label, weight 256 | * \param array pointer to float vector 257 | * \param len length of array 258 | * \return 0 when success, -1 when failure happens 259 | */ 260 | XGB_DLL int XGDMatrixSetFloatInfo(DMatrixHandle handle, 261 | const char *field, 262 | const float *array, 263 | bst_ulong len); 264 | /*! 265 | * \brief set uint32 vector to a content in info 266 | * \param handle a instance of data matrix 267 | * \param field field name 268 | * \param array pointer to float vector 269 | * \param len length of array 270 | * \return 0 when success, -1 when failure happens 271 | */ 272 | XGB_DLL int XGDMatrixSetUIntInfo(DMatrixHandle handle, 273 | const char *field, 274 | const unsigned *array, 275 | bst_ulong len); 276 | /*! 277 | * \brief set label of the training matrix 278 | * \param handle a instance of data matrix 279 | * \param group pointer to group size 280 | * \param len length of array 281 | * \return 0 when success, -1 when failure happens 282 | */ 283 | XGB_DLL int XGDMatrixSetGroup(DMatrixHandle handle, 284 | const unsigned *group, 285 | bst_ulong len); 286 | /*! 287 | * \brief get float info vector from matrix 288 | * \param handle a instance of data matrix 289 | * \param field field name 290 | * \param out_len used to set result length 291 | * \param out_dptr pointer to the result 292 | * \return 0 when success, -1 when failure happens 293 | */ 294 | XGB_DLL int XGDMatrixGetFloatInfo(const DMatrixHandle handle, 295 | const char *field, 296 | bst_ulong* out_len, 297 | const float **out_dptr); 298 | /*! 299 | * \brief get uint32 info vector from matrix 300 | * \param handle a instance of data matrix 301 | * \param field field name 302 | * \param out_len The length of the field. 303 | * \param out_dptr pointer to the result 304 | * \return 0 when success, -1 when failure happens 305 | */ 306 | XGB_DLL int XGDMatrixGetUIntInfo(const DMatrixHandle handle, 307 | const char *field, 308 | bst_ulong* out_len, 309 | const unsigned **out_dptr); 310 | /*! 311 | * \brief get number of rows. 312 | * \param handle the handle to the DMatrix 313 | * \param out The address to hold number of rows. 314 | * \return 0 when success, -1 when failure happens 315 | */ 316 | XGB_DLL int XGDMatrixNumRow(DMatrixHandle handle, 317 | bst_ulong *out); 318 | /*! 319 | * \brief get number of columns 320 | * \param handle the handle to the DMatrix 321 | * \param out The output of number of columns 322 | * \return 0 when success, -1 when failure happens 323 | */ 324 | XGB_DLL int XGDMatrixNumCol(DMatrixHandle handle, 325 | bst_ulong *out); 326 | // --- start XGBoost class 327 | /*! 328 | * \brief create xgboost learner 329 | * \param dmats matrices that are set to be cached 330 | * \param len length of dmats 331 | * \param out handle to the result booster 332 | * \return 0 when success, -1 when failure happens 333 | */ 334 | XGB_DLL int XGBoosterCreate(const DMatrixHandle dmats[], 335 | bst_ulong len, 336 | BoosterHandle *out); 337 | /*! 338 | * \brief free obj in handle 339 | * \param handle handle to be freed 340 | * \return 0 when success, -1 when failure happens 341 | */ 342 | XGB_DLL int XGBoosterFree(BoosterHandle handle); 343 | 344 | /*! 345 | * \brief set parameters 346 | * \param handle handle 347 | * \param name parameter name 348 | * \param value value of parameter 349 | * \return 0 when success, -1 when failure happens 350 | */ 351 | XGB_DLL int XGBoosterSetParam(BoosterHandle handle, 352 | const char *name, 353 | const char *value); 354 | 355 | /*! 356 | * \brief update the model in one round using dtrain 357 | * \param handle handle 358 | * \param iter current iteration rounds 359 | * \param dtrain training data 360 | * \return 0 when success, -1 when failure happens 361 | */ 362 | XGB_DLL int XGBoosterUpdateOneIter(BoosterHandle handle, 363 | int iter, 364 | DMatrixHandle dtrain); 365 | /*! 366 | * \brief update the model, by directly specify gradient and second order gradient, 367 | * this can be used to replace UpdateOneIter, to support customized loss function 368 | * \param handle handle 369 | * \param dtrain training data 370 | * \param grad gradient statistics 371 | * \param hess second order gradient statistics 372 | * \param len length of grad/hess array 373 | * \return 0 when success, -1 when failure happens 374 | */ 375 | XGB_DLL int XGBoosterBoostOneIter(BoosterHandle handle, 376 | DMatrixHandle dtrain, 377 | float *grad, 378 | float *hess, 379 | bst_ulong len); 380 | /*! 381 | * \brief get evaluation statistics for xgboost 382 | * \param handle handle 383 | * \param iter current iteration rounds 384 | * \param dmats pointers to data to be evaluated 385 | * \param evnames pointers to names of each data 386 | * \param len length of dmats 387 | * \param out_result the string containing evaluation statistics 388 | * \return 0 when success, -1 when failure happens 389 | */ 390 | XGB_DLL int XGBoosterEvalOneIter(BoosterHandle handle, 391 | int iter, 392 | DMatrixHandle dmats[], 393 | const char *evnames[], 394 | bst_ulong len, 395 | const char **out_result); 396 | /*! 397 | * \brief make prediction based on dmat 398 | * \param handle handle 399 | * \param dmat data matrix 400 | * \param option_mask bit-mask of options taken in prediction, possible values 401 | * 0:normal prediction 402 | * 1:output margin instead of transformed value 403 | * 2:output leaf index of trees instead of leaf value, note leaf index is unique per tree 404 | * 4:output feature contributions to individual predictions 405 | * \param ntree_limit limit number of trees used for prediction, this is only valid for boosted trees 406 | * when the parameter is set to 0, we will use all the trees 407 | * \param out_len used to store length of returning result 408 | * \param out_result used to set a pointer to array 409 | * \return 0 when success, -1 when failure happens 410 | */ 411 | XGB_DLL int XGBoosterPredict(BoosterHandle handle, 412 | DMatrixHandle dmat, 413 | int option_mask, 414 | unsigned ntree_limit, 415 | bst_ulong *out_len, 416 | const float **out_result); 417 | 418 | /*! 419 | * \brief load model from existing file 420 | * \param handle handle 421 | * \param fname file name 422 | * \return 0 when success, -1 when failure happens 423 | */ 424 | XGB_DLL int XGBoosterLoadModel(BoosterHandle handle, 425 | const char *fname); 426 | /*! 427 | * \brief save model into existing file 428 | * \param handle handle 429 | * \param fname file name 430 | * \return 0 when success, -1 when failure happens 431 | */ 432 | XGB_DLL int XGBoosterSaveModel(BoosterHandle handle, 433 | const char *fname); 434 | /*! 435 | * \brief load model from in memory buffer 436 | * \param handle handle 437 | * \param buf pointer to the buffer 438 | * \param len the length of the buffer 439 | * \return 0 when success, -1 when failure happens 440 | */ 441 | XGB_DLL int XGBoosterLoadModelFromBuffer(BoosterHandle handle, 442 | const void *buf, 443 | bst_ulong len); 444 | /*! 445 | * \brief save model into binary raw bytes, return header of the array 446 | * user must copy the result out, before next xgboost call 447 | * \param handle handle 448 | * \param out_len the argument to hold the output length 449 | * \param out_dptr the argument to hold the output data pointer 450 | * \return 0 when success, -1 when failure happens 451 | */ 452 | XGB_DLL int XGBoosterGetModelRaw(BoosterHandle handle, 453 | bst_ulong *out_len, 454 | const char **out_dptr); 455 | /*! 456 | * \brief dump model, return array of strings representing model dump 457 | * \param handle handle 458 | * \param fmap name to fmap can be empty string 459 | * \param with_stats whether to dump with statistics 460 | * \param out_len length of output array 461 | * \param out_dump_array pointer to hold representing dump of each model 462 | * \return 0 when success, -1 when failure happens 463 | */ 464 | XGB_DLL int XGBoosterDumpModel(BoosterHandle handle, 465 | const char *fmap, 466 | int with_stats, 467 | bst_ulong *out_len, 468 | const char ***out_dump_array); 469 | 470 | /*! 471 | * \brief dump model, return array of strings representing model dump 472 | * \param handle handle 473 | * \param fmap name to fmap can be empty string 474 | * \param with_stats whether to dump with statistics 475 | * \param format the format to dump the model in 476 | * \param out_len length of output array 477 | * \param out_dump_array pointer to hold representing dump of each model 478 | * \return 0 when success, -1 when failure happens 479 | */ 480 | XGB_DLL int XGBoosterDumpModelEx(BoosterHandle handle, 481 | const char *fmap, 482 | int with_stats, 483 | const char *format, 484 | bst_ulong *out_len, 485 | const char ***out_dump_array); 486 | 487 | /*! 488 | * \brief dump model, return array of strings representing model dump 489 | * \param handle handle 490 | * \param fnum number of features 491 | * \param fname names of features 492 | * \param ftype types of features 493 | * \param with_stats whether to dump with statistics 494 | * \param out_len length of output array 495 | * \param out_models pointer to hold representing dump of each model 496 | * \return 0 when success, -1 when failure happens 497 | */ 498 | XGB_DLL int XGBoosterDumpModelWithFeatures(BoosterHandle handle, 499 | int fnum, 500 | const char **fname, 501 | const char **ftype, 502 | int with_stats, 503 | bst_ulong *out_len, 504 | const char ***out_models); 505 | 506 | /*! 507 | * \brief dump model, return array of strings representing model dump 508 | * \param handle handle 509 | * \param fnum number of features 510 | * \param fname names of features 511 | * \param ftype types of features 512 | * \param with_stats whether to dump with statistics 513 | * \param format the format to dump the model in 514 | * \param out_len length of output array 515 | * \param out_models pointer to hold representing dump of each model 516 | * \return 0 when success, -1 when failure happens 517 | */ 518 | XGB_DLL int XGBoosterDumpModelExWithFeatures(BoosterHandle handle, 519 | int fnum, 520 | const char **fname, 521 | const char **ftype, 522 | int with_stats, 523 | const char *format, 524 | bst_ulong *out_len, 525 | const char ***out_models); 526 | 527 | /*! 528 | * \brief Get string attribute from Booster. 529 | * \param handle handle 530 | * \param key The key of the attribute. 531 | * \param out The result attribute, can be NULL if the attribute do not exist. 532 | * \param success Whether the result is contained in out. 533 | * \return 0 when success, -1 when failure happens 534 | */ 535 | XGB_DLL int XGBoosterGetAttr(BoosterHandle handle, 536 | const char* key, 537 | const char** out, 538 | int *success); 539 | /*! 540 | * \brief Set or delete string attribute. 541 | * 542 | * \param handle handle 543 | * \param key The key of the attribute. 544 | * \param value The value to be saved. 545 | * If nullptr, the attribute would be deleted. 546 | * \return 0 when success, -1 when failure happens 547 | */ 548 | XGB_DLL int XGBoosterSetAttr(BoosterHandle handle, 549 | const char* key, 550 | const char* value); 551 | /*! 552 | * \brief Get the names of all attribute from Booster. 553 | * \param handle handle 554 | * \param out_len the argument to hold the output length 555 | * \param out pointer to hold the output attribute stings 556 | * \return 0 when success, -1 when failure happens 557 | */ 558 | XGB_DLL int XGBoosterGetAttrNames(BoosterHandle handle, 559 | bst_ulong* out_len, 560 | const char*** out); 561 | 562 | // --- Distributed training API---- 563 | // NOTE: functions in rabit/c_api.h will be also available in libxgboost.so 564 | /*! 565 | * \brief Initialize the booster from rabit checkpoint. 566 | * This is used in distributed training API. 567 | * \param handle handle 568 | * \param version The output version of the model. 569 | * \return 0 when success, -1 when failure happens 570 | */ 571 | XGB_DLL int XGBoosterLoadRabitCheckpoint( 572 | BoosterHandle handle, 573 | int* version); 574 | 575 | /*! 576 | * \brief Save the current checkpoint to rabit. 577 | * \param handle handle 578 | * \return 0 when success, -1 when failure happens 579 | */ 580 | XGB_DLL int XGBoosterSaveRabitCheckpoint(BoosterHandle handle); 581 | 582 | #endif // XGBOOST_C_API_H_ 583 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | input: 'src/index.js', 3 | output: { 4 | format: 'cjs', 5 | file: 'lib/index.js' 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /src/__tests__/test.js: -------------------------------------------------------------------------------- 1 | import IrisDataset from 'ml-dataset-iris'; 2 | import ConfusionMatrix from 'ml-confusion-matrix'; 3 | 4 | describe('xgboost test (WASM)', () => { 5 | it('basic test on iris dataset', async () => { 6 | var XGBoostWASM = await require('..'); 7 | var booster = new XGBoostWASM({ 8 | objective: 'multi:softmax' 9 | }); 10 | var dataset = IrisDataset.getNumbers(); 11 | var trueLabels = IrisDataset.getClasses().map((elem) => IrisDataset.getDistinctClasses().indexOf(elem)); 12 | 13 | booster.train(dataset, trueLabels); 14 | var predictions = booster.predict(dataset); 15 | var cm = ConfusionMatrix.fromLabels(trueLabels, predictions); 16 | 17 | expect(cm.getF1Score(0)).toBe(1); 18 | expect(cm.getF1Score(1)).toBe(1); 19 | expect(cm.getF1Score(2)).toBe(1); 20 | 21 | booster.free(); 22 | }); 23 | 24 | it('load and save test', async () => { 25 | var XGBoostWASM = await require('..'); 26 | var booster = new XGBoostWASM({ 27 | objective: 'multi:softmax' 28 | }); 29 | var dataset = IrisDataset.getNumbers(); 30 | var trueLabels = IrisDataset.getClasses().map((elem) => IrisDataset.getDistinctClasses().indexOf(elem)); 31 | 32 | booster.train(dataset, trueLabels); 33 | 34 | var model = JSON.parse(JSON.stringify(booster)); 35 | booster = XGBoostWASM.load(model); 36 | 37 | var predictions = booster.predict(dataset); 38 | var cm = ConfusionMatrix.fromLabels(trueLabels, predictions); 39 | 40 | expect(cm.getF1Score(0)).toBe(1); 41 | expect(cm.getF1Score(1)).toBe(1); 42 | expect(cm.getF1Score(2)).toBe(1); 43 | 44 | booster.free(); 45 | }); 46 | 47 | it('load from model trained on other programming language', async () => { 48 | var XGBoost = await require('..'); 49 | 50 | var booster = XGBoost.loadFromModel('./models/output.model', { 51 | labels: [0, 1, 2] 52 | }); 53 | var dataset = IrisDataset.getNumbers(); 54 | var trueLabels = IrisDataset.getClasses().map((elem) => IrisDataset.getDistinctClasses().indexOf(elem)); 55 | 56 | expect(() => { 57 | var model = XGBoost.loadFromModel('./models/output.model', { 58 | labels: [0, 1, 2, 3, 4] 59 | }); 60 | model.predict(dataset); 61 | }).toThrowError('The number of labels is not the same as the prediction size. Labels: 5, Prediction size: 3'); 62 | 63 | var predictions = booster.predict(dataset); 64 | var cm = ConfusionMatrix.fromLabels(trueLabels, predictions); 65 | 66 | expect(cm.getF1Score(0)).toBe(1); 67 | expect(cm.getF1Score(1)).toBe(1); 68 | expect(cm.getF1Score(2)).toBe(1); 69 | 70 | booster.free(); 71 | }); 72 | }); 73 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import loadXGBoost from './loadXGBoost'; 2 | 3 | var xgboostWASM = require('../dist/wasm/xgboost'); 4 | 5 | module.exports = xgboostWASM.isReady.then((l) => loadXGBoost(l)); 6 | -------------------------------------------------------------------------------- /src/loadXGBoost.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | 3 | import Matrix from 'ml-matrix'; 4 | 5 | 6 | export default function loadXGBoost(xgboost) { 7 | /* eslint-disable camelcase */ 8 | const create_model = xgboost.cwrap('create_model', 'number', ['array', 'array', 'number', 'number']); 9 | const free_model = xgboost.cwrap('free_memory_model', null, ['number']); 10 | const set_param = xgboost.cwrap('set_param', null, ['number', 'string', 'string']); 11 | const train = xgboost.cwrap('train_full_model', null, ['number', 'number']); 12 | const predict_one = xgboost.cwrap('predict_one', 'number', ['number', 'array', 'number', 'number']); 13 | const predict_size = xgboost.cwrap('prediction_size', 'number', ['number', 'array', 'number', 'number']); 14 | const save_model = xgboost.cwrap('save_model', 'number', ['number']); 15 | const get_file_content = xgboost.cwrap('get_file_content', null, ['number', 'number']); 16 | const load_model = xgboost.cwrap('load_model', 'number', ['number', 'number']); 17 | 18 | const defaultOptions = { 19 | booster: 'gbtree', 20 | objective: 'reg:linear', 21 | max_depth: 5, 22 | eta: 0.1, 23 | min_child_weight: 1, 24 | subsample: 0.5, 25 | colsample_bytree: 1, 26 | silent: 1, 27 | iterations: 200, 28 | predictionSize: 1 29 | }; 30 | /* eslint-enable camelcase */ 31 | 32 | 33 | class XGBoost { 34 | 35 | /** 36 | * @constructor 37 | * @param {object} options - Same parameters described [here](https://github.com/dmlc/xgboost/blob/master/doc/parameter.md), Default parameters below. 38 | * @param {string} [options.booster='gbtree'] 39 | * @param {string} [options.objective='reg:linear'] 40 | * @param {number} [options.max_depth=5] 41 | * @param {number} [options.eta=0.1] 42 | * @param {number} [options.min_child_weight=1] 43 | * @param {number} [options.subsample=0.5] 44 | * @param {number} [options.colsample_bytree=1] 45 | * @param {number} [options.silent=1] 46 | * @param {number} [options.iterations=200] 47 | * @param {object} model - for load purposes. 48 | */ 49 | constructor(options, model) { 50 | if (options === true) { 51 | var array = new Uint8Array(model.model); 52 | var offset = xgboost._malloc(array.length); 53 | xgboost.HEAPU8.set(array, offset); 54 | this.model = load_model(offset, array.length); 55 | xgboost._free(offset); 56 | 57 | if (this.model === 0) { 58 | throw new Error('Error while loading the model!'); 59 | } 60 | this.options = model.options; 61 | } else { 62 | this.checkLabels = options.objective === 'multi:softmax'; 63 | this.options = Object.assign({}, defaultOptions, options); 64 | } 65 | 66 | for (var key in this.options) { 67 | if (key === 'iterations' || key === 'labels') { 68 | continue; 69 | } 70 | this.options[key] = this.options[key].toString(); 71 | } 72 | } 73 | 74 | /** 75 | * Train the decision tree with the given training set and labels. 76 | * @param {Matrix|Array>} trainingSet 77 | * @param {Array} trainingValues 78 | */ 79 | train(trainingSet, trainingValues) { 80 | if (this.checkLabels) { 81 | /* eslint-disable camelcase */ 82 | this.options.num_class = new Set(trainingValues).size.toString(); 83 | /* eslint-enable camelcase */ 84 | } 85 | 86 | var X = Matrix.checkMatrix(trainingSet); 87 | var rows = X.rows; 88 | var cols = X.columns; 89 | 90 | var flattenData = X.to1DArray(); 91 | this.model = create_model(new Uint8Array(Float32Array.from(flattenData).buffer), new Uint8Array(Float32Array.from(trainingValues).buffer), rows, cols); 92 | var variables = Object.keys(this.options); 93 | for (var i = 0; i < variables.length; ++i) { 94 | var variable = variables[i]; 95 | if (variable === 'iterations') { 96 | continue; 97 | } 98 | 99 | var value = this.options[variable]; 100 | set_param(this.model, variable, value); 101 | } 102 | 103 | train(this.model, this.options.iterations); 104 | } 105 | 106 | /** 107 | * Predicts the output given the matrix to predict. 108 | * @param {Matrix|Array>} toPredict 109 | * @return {Array} predictions 110 | */ 111 | predict(toPredict) { 112 | var Xtest = Matrix.checkMatrix(toPredict); 113 | var predictions = new Array(Xtest.rows); 114 | var predictionSize = predict_size(this.model, new Uint8Array(Float32Array.from(Xtest.getRow(0)).buffer), Xtest.columns, undefined); 115 | if (this.options.labels && this.options.labels.length !== predictionSize) { 116 | throw new RangeError(`The number of labels is not the same as the prediction size. Labels: ${this.options.labels.length}, Prediction size: ${predictionSize}`); 117 | } 118 | 119 | for (var i = 0; i < Xtest.rows; i++) { 120 | var current = Xtest.getRow(i); 121 | var predictionPointer = xgboost._malloc(predictionSize * 4); 122 | xgboost.HEAPF32.set(new Float32Array(predictionSize), predictionPointer / 4); 123 | 124 | 125 | predictionSize = predict_one(this.model, new Uint8Array(Float32Array.from(current).buffer), Xtest.columns, predictionPointer); 126 | 127 | var isSizeOne = predictionSize === 1; 128 | var prediction = isSizeOne ? xgboost.getValue(predictionPointer, 'float') : new Array(predictionSize); 129 | if (!isSizeOne) { 130 | for (var j = 0; j < predictionSize; ++j) { 131 | prediction[j] = xgboost.getValue(predictionPointer + j * 4, 'float'); 132 | } 133 | } 134 | predictions[i] = prediction; 135 | xgboost._free(predictionPointer); 136 | } 137 | 138 | if (this.options.labels) { 139 | var predictedLabels = new Array(predictions.length); 140 | predictions = Matrix.checkMatrix(predictions); 141 | for (i = 0; i < predictions.length; ++i) { 142 | predictedLabels[i] = this.options.labels[predictions.maxRowIndex(i)[1]]; 143 | } 144 | 145 | predictions = predictedLabels; 146 | } 147 | 148 | return predictions; 149 | } 150 | 151 | /** 152 | * Export the current model to JSON. 153 | * @return {object} - Current model. 154 | */ 155 | toJSON() { 156 | if (!this.model) throw new Error('No model trained to save'); 157 | var size = save_model(this.model); 158 | if (size === -1) { 159 | throw new Error('Error while saving the model, please report this error'); 160 | } 161 | 162 | var offset = xgboost._malloc(size); 163 | xgboost.HEAPU8.set(new Uint8Array(size), offset); 164 | get_file_content(offset, size); 165 | var array = new Array(size); 166 | for (var i = 0; i < size; ++i) { 167 | array[i] = xgboost.getValue(offset + i, 'i8'); 168 | } 169 | xgboost._free(offset); 170 | 171 | return { 172 | name: 'ml-xgboost', 173 | model: array, 174 | options: this.options 175 | }; 176 | } 177 | 178 | /** 179 | * Load a Decision tree classifier with the given model. 180 | * @param {object} model 181 | * @return {XGBoost} 182 | */ 183 | static load(model) { 184 | if (model.name !== 'ml-xgboost') { 185 | throw new RangeError(`Invalid model: ${model.name}`); 186 | } 187 | 188 | return new XGBoost(true, model); 189 | } 190 | 191 | /** 192 | * Load a model trained from other programming language 193 | * @param {string} filepath 194 | * @param {object} options 195 | * @param {Array} [options.labels] - Some classifiers are trained with a one-hot encoder (Ex: Python API) so the 196 | * current classifier returns the probability of each class, if you want the single predictions, you should provide 197 | * an array with the corresponding labels, if you are doing regression you should ignore this option 198 | * @return {XGBoost} model 199 | */ 200 | static loadFromModel(filepath, options = {}) { 201 | var binary = fs.readFileSync(filepath); 202 | return new XGBoost(true, { 203 | model: binary, 204 | options: options 205 | }); 206 | } 207 | 208 | /** 209 | * Free the memory allocated for the model. Since this memory is stored in the memory model of emscripten, 210 | * it is allocated within an ArrayBuffer and WILL NOT BE GARBARGE COLLECTED, you have to explicitly free it. 211 | * So not calling this will result in memory leaks. As of today in the browser, there is no way to hook the 212 | * garbage collection of the XGBoost object to free it automatically. Free the memory that was created by the 213 | * compiled XGBoost library to. store the model. This model is reused every time the predict method is called. 214 | */ 215 | free() { 216 | free_model(this.model); 217 | } 218 | } 219 | 220 | return XGBoost; 221 | } 222 | -------------------------------------------------------------------------------- /src/wasmPreJS.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | var Module = module.exports = {}; 4 | if (typeof self === 'undefined') { 5 | // When loaded with nodejs, the absolute file path is needed 6 | Module.wasmBinaryFile = path.resolve(__dirname, 'xgboost.wasm'); 7 | } else { 8 | Module.wasmBinaryFile = 'xgboost.wasm'; 9 | } 10 | 11 | Module.isReady = new Promise(function (resolve) { 12 | Module.onRuntimeInitialized = function () { 13 | resolve(Module); 14 | }; 15 | }); 16 | --------------------------------------------------------------------------------