├── .github └── workflows │ ├── changelog.json │ ├── commit.yml │ └── main.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── ci.sh ├── libc └── bsearch.c ├── libm ├── COPYRIGHT ├── README ├── __cos.c ├── __rem_pio2.c ├── __rem_pio2_large.c ├── __sin.c ├── cos.c ├── endian.h ├── exp.c ├── features.h ├── floor.c ├── fmaxf.c ├── fminf.c ├── fp_arch.h ├── frexp.c ├── libm.h ├── log1p.c ├── round.c ├── scalbn.c ├── sin.c └── sqrt.c ├── libtf.cc ├── libtf.h ├── libtf ├── LICENSE ├── README ├── cortex-m0plus │ └── libtf.a ├── cortex-m4 │ └── libtf.a ├── cortex-m55 │ └── libtf.a ├── cortex-m7 │ └── libtf.a ├── libtf.h └── models │ ├── person_detection.tflite │ └── person_detection.txt └── make.py /.github/workflows/changelog.json: -------------------------------------------------------------------------------- 1 | { 2 | "categories": [ 3 | { 4 | "title": "ignore", 5 | "labels": ["github"] 6 | }, 7 | { 8 | "title": "## 🪄 LibTf", 9 | "labels": ["libtf"] 10 | }, 11 | { 12 | "title": "## 🧬 EdgeImpulse", 13 | "labels": ["edgeimpulse"] 14 | }, 15 | { 16 | "title": "## 📚 TensorFlow", 17 | "labels": ["tensorflow"] 18 | } 19 | ], 20 | "ignore_labels": [ 21 | "github" 22 | ], 23 | "label_extractor": [ 24 | { 25 | "pattern": "^libtf", 26 | "method": "match", 27 | "on_property": "title" 28 | }, 29 | { 30 | "pattern": "^edgeimpulse", 31 | "method": "match", 32 | "on_property": "title" 33 | }, 34 | { 35 | "pattern": "^tensorflow", 36 | "method": "match", 37 | "on_property": "title" 38 | } 39 | ], 40 | "transformers": [ 41 | { 42 | "pattern": "^(.*)\/(.+:.*)", 43 | "target": "- $2" 44 | } 45 | ], 46 | "sort": "DESC", 47 | "template": "${{CHANGELOG}}\n\n## 🪛 Misc Fixes:\n\n${{UNCATEGORIZED}}\n", 48 | "pr_template": "- ${{TITLE}}", 49 | "empty_template": "- no changes", 50 | "max_tags_to_fetch": 100, 51 | "max_pull_requests": 100, 52 | "max_back_track_time_days": 100 53 | } 54 | -------------------------------------------------------------------------------- /.github/workflows/commit.yml: -------------------------------------------------------------------------------- 1 | name: '📜 Check Commit Messages' 2 | 3 | on: 4 | pull_request: 5 | types: 6 | - opened 7 | - edited 8 | - reopened 9 | - synchronize 10 | branches: 11 | - 'master' 12 | 13 | jobs: 14 | check-commit-messages: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: '📜 Check commit messages format' 18 | uses: gsactions/commit-message-checker@v2 19 | with: 20 | pattern: '^[^!]+: [A-Za-z]+.+ .+\.$' 21 | flags: 'gm' 22 | error: 'Commit subject line must match the following pattern: : .' 23 | excludeTitle: 'false' 24 | excludeDescription: 'true' 25 | checkAllCommitMessages: 'true' 26 | accessToken: ${{ secrets.GITHUB_TOKEN }} 27 | - name: '📜 Check commit messages length' 28 | uses: gsactions/commit-message-checker@v2 29 | with: 30 | pattern: '^[^#].{10,78}$' 31 | error: 'Commit subject line maximum line length of 78 characters is exceeded.' 32 | excludeTitle: 'false' 33 | excludeDescription: 'true' 34 | checkAllCommitMessages: 'true' 35 | accessToken: ${{ secrets.GITHUB_TOKEN }} 36 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: 'CI' 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*.*.*' 7 | branches: 8 | - 'master' 9 | 10 | pull_request: 11 | branches: 12 | - 'master' 13 | 14 | jobs: 15 | build: 16 | runs-on: ubuntu-20.04 17 | steps: 18 | - name: '⏳ Checkout repository' 19 | uses: actions/checkout@v3 20 | with: 21 | submodules: true 22 | 23 | - name: '🧱 Update submodules' 24 | run: source ci.sh && ci_update_submodules 25 | 26 | - name: '♻ Caching dependencies' 27 | uses: actions/cache@v3.3.1 28 | id: cache 29 | with: 30 | path: ~/cache/gcc 31 | key: 'gcc-arm-none-eabi-10-2020-q4-major' 32 | 33 | - name: '🛠 Install toolchain ' 34 | if: steps.cache.outputs.cache-hit != 'true' 35 | run: source ci.sh && ci_install_arm_gcc 36 | 37 | - name: '🏗 Build firmware' 38 | run: source ci.sh && ci_build 39 | 40 | - name: '⬆ Upload artifacts' 41 | if: github.event_name != 'pull_request' 42 | uses: actions/upload-artifact@v3 43 | with: 44 | name: libtf 45 | path: libtf 46 | if-no-files-found: error 47 | 48 | stable-release: 49 | needs: build 50 | runs-on: ubuntu-latest 51 | if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') 52 | steps: 53 | - name: '⏳ Checkout repository' 54 | uses: actions/checkout@v3 55 | with: 56 | submodules: false 57 | 58 | - name: '🤌 Download artifacts' 59 | uses: actions/download-artifact@v3 60 | with: 61 | name: libtf 62 | path: libtf 63 | 64 | - name: "✏️ Generate release changelog" 65 | id: changelog 66 | uses: mikepenz/release-changelog-builder-action@v3 67 | with: 68 | toTag: ${{ github.sha }} 69 | configuration: '.github/workflows/changelog.json' 70 | env: 71 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 72 | 73 | - name: '📦 Package firmware' 74 | run: source ci.sh && ci_package_release 75 | 76 | - name: '🔥 Create stable release' 77 | uses: softprops/action-gh-release@v1 78 | with: 79 | draft: true 80 | files: libtf.zip 81 | body: ${{steps.changelog.outputs.changelog}} 82 | env: 83 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 84 | 85 | - name: '🧹 Remove artifacts' 86 | uses: geekyeggo/delete-artifact@v1 87 | with: 88 | name: libtf 89 | failOnError: false 90 | 91 | development-release: 92 | needs: build 93 | runs-on: ubuntu-latest 94 | if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') == false 95 | permissions: 96 | contents: write 97 | steps: 98 | - name: '⏳ Checkout repository' 99 | uses: actions/checkout@v3 100 | with: 101 | submodules: false 102 | 103 | - name: '🤌 Download artifacts' 104 | uses: actions/download-artifact@v3 105 | with: 106 | name: libtf 107 | path: libtf 108 | 109 | - name: '📦 Package firmware' 110 | run: source ci.sh && ci_package_development 111 | 112 | - name: '🧹 Delete old release' 113 | uses: dev-drprasad/delete-tag-and-release@v0.2.1 114 | with: 115 | delete_release: true 116 | tag_name: development 117 | env: 118 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 119 | 120 | - name: "✏️ Generate release changelog" 121 | id: changelog 122 | uses: mikepenz/release-changelog-builder-action@v3 123 | with: 124 | toTag: ${{ github.sha }} 125 | configuration: '.github/workflows/changelog.json' 126 | env: 127 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 128 | 129 | - name: '🔥 Create development release' 130 | uses: softprops/action-gh-release@v1 131 | with: 132 | draft: false 133 | name: Development Release 134 | tag_name: development 135 | body: | 136 | **⚠️ This is a development release, and it may be unstable.** 137 | ${{steps.changelog.outputs.changelog}} 138 | files: libtf.zip 139 | env: 140 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 141 | 142 | - name: '🧹 Remove artifacts' 143 | uses: geekyeggo/delete-artifact@v1 144 | with: 145 | name: libtf 146 | failOnError: false 147 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | /build/ 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "edge-impulse-sdk"] 2 | path = edge-impulse-sdk 3 | url = git@github.com:openmv/tensorflow.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019-2024 OpenMV 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![GitHub Build](https://github.com/openmv/tensorflow-lib/actions/workflows/main.yml/badge.svg)](https://github.com/openmv/tensorflow-lib/actions/workflows/main.yml) 2 | [![GitHub license](https://img.shields.io/github/license/openmv/tensorflow-lib?label=license%20%E2%9A%96)](https://github.com/openmv/tensorflow-lib/blob/master/LICENSE) 3 | ![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/openmv/tensorflow-lib?sort=semver) 4 | [![GitHub forks](https://img.shields.io/github/forks/openmv/tensorflow-lib?color=green)](https://github.com/openmv/tensorflow-lib/network) 5 | [![GitHub stars](https://img.shields.io/github/stars/openmv/tensorflow-lib?color=yellow)](https://github.com/openmv/tensorflow-lib/stargazers) 6 | [![GitHub issues](https://img.shields.io/github/issues/openmv/tensorflow-lib?color=orange)](https://github.com/openmv/tensorflow-lib/issues) 7 | 8 | 9 | 10 | # Archived 11 | 12 | This repo has been archived and replaced with the new [tlfm](https://github.com/openmv/tflm) repo in OpenMV firmware. The new `tflm` repo includes a compiled copy of the entire tensorflow lite for microcontrollers library with all headers for various targets generated by github actions. 13 | 14 | # A Portable C Tensorflow Library 15 | 16 | Full featured Tensorflow package for Cortex-M0-Plus, Cortex-M4, Cortex-M7, and Cortex-M55 CPUs with **no external dependencies**! 17 | 18 | - [Instructions for building](#instructions-for-building) 19 | - [Prebuilt Files](#prebuilt-files) 20 | - [Contributing to the project](#contributing-to-the-project) 21 | + [Contribution guidelines](#contribution-guidelines) 22 | 23 | ## Instructions for building 24 | 25 | 1. Clone this repo recursively: 26 | 27 | git clone --recursive https://github.com/openmv/tensorflow-lib.git 28 | 29 | 2. If you already have `arm-none-eabi-gcc` installed and available on your path do: 30 | 31 | python make.py 32 | 33 | 3. Otherwise, install GCC (only needs to be done once): 34 | 35 | source ci.sh && ci_install_arm_gcc 36 | 37 | 4. And then do: 38 | 39 | source ci.sh ci_build 40 | 41 | You will need to use the `source ci.sh ci_build` to compile the library if you installed gcc via `source ci.sh && ci_install_arm_gcc` and did not add GCC to your path. 42 | 43 | ### Edge Impulse SDK (TensorFlow) Changes 44 | 45 | If you edit anything in the Edge Impulse SDK (TensorFlow) repo, make sure to do `python make.py --clean` afterward to delete any cached changes. Otherwise, you may get confusing errors. 46 | 47 | ## Prebuilt Files 48 | 49 | You can find libtf pre-built under [releases](https://github.com/openmv/tensorflow-lib/releases). Alternatively, you may include this repo as a submodule and use [libtf](libtf) directly from the repo. This will allow you to easily update libtf without having to store the binaries directly in your repo. 50 | 51 | ## Contributing to the project 52 | 53 | Contributions are most welcome. If you are interested in contributing to the project, start by creating a fork of each of the following repositories: 54 | 55 | * https://github.com/openmv/tensorflow-lib.git 56 | * https://github.com/openmv/tensorflow.git 57 | 58 | Clone the forked tensorflow-lib repository, and add a remote to the main tensorflow-lib repository: 59 | ```bash 60 | git clone --recursive https://github.com//tensorflow-lib.git 61 | git -C tensorflow-lib remote add upstream https://github.com/openmv/tensorflow-lib.git 62 | ``` 63 | 64 | Set the `origin` remote of the tensorflow submodule to the forked tensorflow repo: 65 | ```bash 66 | git -C tensorflow-lib/edge-impulse-sdk remote set-url origin https://github.com//tensorflow.git 67 | ``` 68 | 69 | Finally add a remote to openmv's tensorflow fork: 70 | ```bash 71 | git -C tensorflow-lib/edge-impulse-sdk remote add upstream https://github.com/openmv/tensorflow.git 72 | ``` 73 | 74 | Now the repositories are ready for pull requests. To send a pull request, create a new feature branch and push it to origin, and use Github to create the pull request from the forked repository to the upstream openmv/micropython repository. For example: 75 | ```bash 76 | git checkout -b 77 | 78 | git push origin -u 79 | ``` 80 | 81 | ### Contribution guidelines 82 | Please follow the [best practices](https://developers.google.com/blockly/guides/modify/contribute/write_a_good_pr) when sending pull requests upstream. In general, the pull request should: 83 | * Fix one problem. Don't try to tackle multiple issues at once. 84 | * Split the changes into logical groups using git commits. 85 | * Pull request title should be less than 78 characters, and match this pattern: 86 | * `:<1 space><.>` 87 | * Commit subject line should be less than 78 characters, and match this pattern: 88 | * `:<1 space><.>` 89 | -------------------------------------------------------------------------------- /ci.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ######################################################################################## 4 | # Install ARM GCC. 5 | TOOLCHAIN_PATH=${HOME}/cache/gcc 6 | TOOLCHAIN_URL="https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x86_64-arm-none-eabi.tar.xz" 7 | 8 | ci_install_arm_gcc_apt() { 9 | sudo apt-get install gcc-arm-none-eabi libnewlib-arm-none-eabi 10 | arm-none-eabi-gcc --version 11 | } 12 | 13 | ci_install_arm_gcc() { 14 | mkdir -p ${TOOLCHAIN_PATH} 15 | wget --no-check-certificate -O - ${TOOLCHAIN_URL} | tar --strip-components=1 -Jx -C ${TOOLCHAIN_PATH} 16 | export PATH=${TOOLCHAIN_PATH}/bin:${PATH} 17 | arm-none-eabi-gcc --version 18 | } 19 | 20 | ######################################################################################## 21 | # Update Submodules. 22 | 23 | ci_update_submodules() { 24 | git submodule update --init --recursive 25 | } 26 | 27 | ######################################################################################## 28 | # Build Targets. 29 | 30 | ci_build() { 31 | export PATH=${TOOLCHAIN_PATH}/bin:${PATH} 32 | python make.py 33 | } 34 | 35 | ######################################################################################## 36 | # Prepare Firmware Packages. 37 | 38 | ci_package_release() { 39 | (cd libtf && zip -r ../libtf.zip *) 40 | } 41 | 42 | ci_package_development() { 43 | (cd libtf && zip -r ../libtf.zip *) 44 | } 45 | -------------------------------------------------------------------------------- /libc/bsearch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1990 Regents of the University of California. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. [rescinded 22 July 1999] 14 | * 4. Neither the name of the University nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 | * SUCH DAMAGE. 29 | */ 30 | 31 | #include 32 | 33 | /* 34 | * Perform a binary search. 35 | * 36 | * The code below is a bit sneaky. After a comparison fails, we 37 | * divide the work in half by moving either left or right. If lim 38 | * is odd, moving left simply involves halving lim: e.g., when lim 39 | * is 5 we look at item 2, so we change lim to 2 so that we will 40 | * look at items 0 & 1. If lim is even, the same applies. If lim 41 | * is odd, moving right again involes halving lim, this time moving 42 | * the base up one item past p: e.g., when lim is 5 we change base 43 | * to item 3 and make lim 2 so that we will look at items 3 and 4. 44 | * If lim is even, however, we have to shrink it by one before 45 | * halving: e.g., when lim is 4, we still looked at item 2, so we 46 | * have to make lim 3, then halve, obtaining 1, so that we will only 47 | * look at item 3. 48 | */ 49 | void * 50 | bsearch (const void *key, const void *base0, 51 | size_t nmemb, size_t size, 52 | int (*compar)(const void *, const void *)) 53 | { 54 | const char *base = (const char *) base0; 55 | int lim, cmp; 56 | const void *p; 57 | 58 | for (lim = nmemb; lim != 0; lim >>= 1) { 59 | p = base + (lim >> 1) * size; 60 | cmp = (*compar)(key, p); 61 | if (cmp == 0) 62 | return (void *)p; 63 | if (cmp > 0) { /* key > p: move right */ 64 | base = (const char *)p + size; 65 | lim--; 66 | } /* else move left */ 67 | } 68 | return (NULL); 69 | } 70 | -------------------------------------------------------------------------------- /libm/COPYRIGHT: -------------------------------------------------------------------------------- 1 | musl as a whole is licensed under the following standard MIT license: 2 | 3 | ---------------------------------------------------------------------- 4 | Copyright © 2005-2014 Rich Felker, et al. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | ---------------------------------------------------------------------- 25 | 26 | Authors/contributors include: 27 | 28 | Anthony G. Basile 29 | Arvid Picciani 30 | Bobby Bingham 31 | Boris Brezillon 32 | Brent Cook 33 | Chris Spiegel 34 | Clément Vasseur 35 | Emil Renner Berthing 36 | Hiltjo Posthuma 37 | Isaac Dunham 38 | Jens Gustedt 39 | Jeremy Huntwork 40 | John Spencer 41 | Justin Cormack 42 | Luca Barbato 43 | Luka Perkov 44 | M Farkas-Dyck (Strake) 45 | Michael Forney 46 | Nicholas J. Kain 47 | orc 48 | Pascal Cuoq 49 | Pierre Carrier 50 | Rich Felker 51 | Richard Pennington 52 | sin 53 | Solar Designer 54 | Stefan Kristiansson 55 | Szabolcs Nagy 56 | Timo Teräs 57 | Valentin Ochs 58 | William Haddon 59 | 60 | Portions of this software are derived from third-party works licensed 61 | under terms compatible with the above MIT license: 62 | 63 | The TRE regular expression implementation (src/regex/reg* and 64 | src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed 65 | under a 2-clause BSD license (license text in the source files). The 66 | included version has been heavily modified by Rich Felker in 2012, in 67 | the interests of size, simplicity, and namespace cleanliness. 68 | 69 | Much of the math library code (src/math/* and src/complex/*) is 70 | Copyright © 1993,2004 Sun Microsystems or 71 | Copyright © 2003-2011 David Schultz or 72 | Copyright © 2003-2009 Steven G. Kargl or 73 | Copyright © 2003-2009 Bruce D. Evans or 74 | Copyright © 2008 Stephen L. Moshier 75 | and labelled as such in comments in the individual source files. All 76 | have been licensed under extremely permissive terms. 77 | 78 | The ARM memcpy code (src/string/armel/memcpy.s) is Copyright © 2008 79 | The Android Open Source Project and is licensed under a two-clause BSD 80 | license. It was taken from Bionic libc, used on Android. 81 | 82 | The implementation of DES for crypt (src/misc/crypt_des.c) is 83 | Copyright © 1994 David Burren. It is licensed under a BSD license. 84 | 85 | The implementation of blowfish crypt (src/misc/crypt_blowfish.c) was 86 | originally written by Solar Designer and placed into the public 87 | domain. The code also comes with a fallback permissive license for use 88 | in jurisdictions that may not recognize the public domain. 89 | 90 | The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011 91 | Valentin Ochs and is licensed under an MIT-style license. 92 | 93 | The BSD PRNG implementation (src/prng/random.c) and XSI search API 94 | (src/search/*.c) functions are Copyright © 2011 Szabolcs Nagy and 95 | licensed under following terms: "Permission to use, copy, modify, 96 | and/or distribute this code for any purpose with or without fee is 97 | hereby granted. There is no warranty." 98 | 99 | The x86_64 port was written by Nicholas J. Kain. Several files (crt) 100 | were released into the public domain; others are licensed under the 101 | standard MIT license terms at the top of this file. See individual 102 | files for their copyright status. 103 | 104 | The mips and microblaze ports were originally written by Richard 105 | Pennington for use in the ellcc project. The original code was adapted 106 | by Rich Felker for build system and code conventions during upstream 107 | integration. It is licensed under the standard MIT terms. 108 | 109 | The powerpc port was also originally written by Richard Pennington, 110 | and later supplemented and integrated by John Spencer. It is licensed 111 | under the standard MIT terms. 112 | 113 | All other files which have no copyright comments are original works 114 | produced specifically for use as part of this library, written either 115 | by Rich Felker, the main author of the library, or by one or more 116 | contibutors listed above. Details on authorship of individual files 117 | can be found in the git version control history of the project. The 118 | omission of copyright and license comments in each file is in the 119 | interest of source tree size. 120 | 121 | All public header files (include/* and arch/*/bits/*) should be 122 | treated as Public Domain as they intentionally contain no content 123 | which can be covered by copyright. Some source modules may fall in 124 | this category as well. If you believe that a file is so trivial that 125 | it should be in the Public Domain, please contact the authors and 126 | request an explicit statement releasing it from copyright. 127 | 128 | The following files are trivial, believed not to be copyrightable in 129 | the first place, and hereby explicitly released to the Public Domain: 130 | 131 | All public headers: include/*, arch/*/bits/* 132 | Startup files: crt/* 133 | -------------------------------------------------------------------------------- /libm/README: -------------------------------------------------------------------------------- 1 | 2 | musl libc 3 | 4 | musl, pronounced like the word "mussel", is an MIT-licensed 5 | implementation of the standard C library targetting the Linux syscall 6 | API, suitable for use in a wide range of deployment environments. musl 7 | offers efficient static and dynamic linking support, lightweight code 8 | and low runtime overhead, strong fail-safe guarantees under correct 9 | usage, and correctness in the sense of standards conformance and 10 | safety. musl is built on the principle that these goals are best 11 | achieved through simple code that is easy to understand and maintain. 12 | 13 | The 1.1 release series for musl features coverage for all interfaces 14 | defined in ISO C99 and POSIX 2008 base, along with a number of 15 | non-standardized interfaces for compatibility with Linux, BSD, and 16 | glibc functionality. 17 | 18 | For basic installation instructions, see the included INSTALL file. 19 | Information on full musl-targeted compiler toolchains, system 20 | bootstrapping, and Linux distributions built on musl can be found on 21 | the project website: 22 | 23 | http://www.musl-libc.org/ 24 | -------------------------------------------------------------------------------- /libm/__cos.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/k_cos.c */ 2 | /* 3 | * ==================================================== 4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 5 | * 6 | * Developed at SunSoft, a Sun Microsystems, Inc. business. 7 | * Permission to use, copy, modify, and distribute this 8 | * software is freely granted, provided that this notice 9 | * is preserved. 10 | * ==================================================== 11 | */ 12 | /* 13 | * __cos( x, y ) 14 | * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 15 | * Input x is assumed to be bounded by ~pi/4 in magnitude. 16 | * Input y is the tail of x. 17 | * 18 | * Algorithm 19 | * 1. Since cos(-x) = cos(x), we need only to consider positive x. 20 | * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0. 21 | * 3. cos(x) is approximated by a polynomial of degree 14 on 22 | * [0,pi/4] 23 | * 4 14 24 | * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x 25 | * where the remez error is 26 | * 27 | * | 2 4 6 8 10 12 14 | -58 28 | * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2 29 | * | | 30 | * 31 | * 4 6 8 10 12 14 32 | * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then 33 | * cos(x) ~ 1 - x*x/2 + r 34 | * since cos(x+y) ~ cos(x) - sin(x)*y 35 | * ~ cos(x) - x*y, 36 | * a correction term is necessary in cos(x) and hence 37 | * cos(x+y) = 1 - (x*x/2 - (r - x*y)) 38 | * For better accuracy, rearrange to 39 | * cos(x+y) ~ w + (tmp + (r-x*y)) 40 | * where w = 1 - x*x/2 and tmp is a tiny correction term 41 | * (1 - x*x/2 == w + tmp exactly in infinite precision). 42 | * The exactness of w + tmp in infinite precision depends on w 43 | * and tmp having the same precision as x. If they have extra 44 | * precision due to compiler bugs, then the extra precision is 45 | * only good provided it is retained in all terms of the final 46 | * expression for cos(). Retention happens in all cases tested 47 | * under FreeBSD, so don't pessimize things by forcibly clipping 48 | * any extra precision in w. 49 | */ 50 | 51 | #include "libm.h" 52 | 53 | static const double 54 | C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ 55 | C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ 56 | C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */ 57 | C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */ 58 | C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ 59 | C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ 60 | 61 | double __cos(double x, double y) 62 | { 63 | double_t hz,z,r,w; 64 | 65 | z = x*x; 66 | w = z*z; 67 | r = z*(C1+z*(C2+z*C3)) + w*w*(C4+z*(C5+z*C6)); 68 | hz = 0.5*z; 69 | w = 1.0-hz; 70 | return w + (((1.0-w)-hz) + (z*r-x*y)); 71 | } 72 | -------------------------------------------------------------------------------- /libm/__rem_pio2.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2.c */ 2 | /* 3 | * ==================================================== 4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 5 | * 6 | * Developed at SunSoft, a Sun Microsystems, Inc. business. 7 | * Permission to use, copy, modify, and distribute this 8 | * software is freely granted, provided that this notice 9 | * is preserved. 10 | * ==================================================== 11 | * 12 | * Optimized by Bruce D. Evans. 13 | */ 14 | /* __rem_pio2(x,y) 15 | * 16 | * return the remainder of x rem pi/2 in y[0]+y[1] 17 | * use __rem_pio2_large() for large x 18 | */ 19 | 20 | #include "libm.h" 21 | 22 | #if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 23 | #define EPS DBL_EPSILON 24 | #elif FLT_EVAL_METHOD==2 25 | #define EPS LDBL_EPSILON 26 | #endif 27 | 28 | /* 29 | * invpio2: 53 bits of 2/pi 30 | * pio2_1: first 33 bit of pi/2 31 | * pio2_1t: pi/2 - pio2_1 32 | * pio2_2: second 33 bit of pi/2 33 | * pio2_2t: pi/2 - (pio2_1+pio2_2) 34 | * pio2_3: third 33 bit of pi/2 35 | * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) 36 | */ 37 | static const double 38 | toint = 1.5/EPS, 39 | pio4 = 0x1.921fb54442d18p-1, 40 | invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ 41 | pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ 42 | pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ 43 | pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ 44 | pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ 45 | pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ 46 | pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ 47 | 48 | /* caller must handle the case when reduction is not needed: |x| ~<= pi/4 */ 49 | int __rem_pio2(double x, double *y) 50 | { 51 | union {double f; uint64_t i;} u = {x}; 52 | double_t z,w,t,r,fn; 53 | double tx[3],ty[2]; 54 | uint32_t ix; 55 | int sign, n, ex, ey, i; 56 | 57 | sign = u.i>>63; 58 | ix = u.i>>32 & 0x7fffffff; 59 | if (ix <= 0x400f6a7a) { /* |x| ~<= 5pi/4 */ 60 | if ((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */ 61 | goto medium; /* cancellation -- use medium case */ 62 | if (ix <= 0x4002d97c) { /* |x| ~<= 3pi/4 */ 63 | if (!sign) { 64 | z = x - pio2_1; /* one round good to 85 bits */ 65 | y[0] = z - pio2_1t; 66 | y[1] = (z-y[0]) - pio2_1t; 67 | return 1; 68 | } else { 69 | z = x + pio2_1; 70 | y[0] = z + pio2_1t; 71 | y[1] = (z-y[0]) + pio2_1t; 72 | return -1; 73 | } 74 | } else { 75 | if (!sign) { 76 | z = x - 2*pio2_1; 77 | y[0] = z - 2*pio2_1t; 78 | y[1] = (z-y[0]) - 2*pio2_1t; 79 | return 2; 80 | } else { 81 | z = x + 2*pio2_1; 82 | y[0] = z + 2*pio2_1t; 83 | y[1] = (z-y[0]) + 2*pio2_1t; 84 | return -2; 85 | } 86 | } 87 | } 88 | if (ix <= 0x401c463b) { /* |x| ~<= 9pi/4 */ 89 | if (ix <= 0x4015fdbc) { /* |x| ~<= 7pi/4 */ 90 | if (ix == 0x4012d97c) /* |x| ~= 3pi/2 */ 91 | goto medium; 92 | if (!sign) { 93 | z = x - 3*pio2_1; 94 | y[0] = z - 3*pio2_1t; 95 | y[1] = (z-y[0]) - 3*pio2_1t; 96 | return 3; 97 | } else { 98 | z = x + 3*pio2_1; 99 | y[0] = z + 3*pio2_1t; 100 | y[1] = (z-y[0]) + 3*pio2_1t; 101 | return -3; 102 | } 103 | } else { 104 | if (ix == 0x401921fb) /* |x| ~= 4pi/2 */ 105 | goto medium; 106 | if (!sign) { 107 | z = x - 4*pio2_1; 108 | y[0] = z - 4*pio2_1t; 109 | y[1] = (z-y[0]) - 4*pio2_1t; 110 | return 4; 111 | } else { 112 | z = x + 4*pio2_1; 113 | y[0] = z + 4*pio2_1t; 114 | y[1] = (z-y[0]) + 4*pio2_1t; 115 | return -4; 116 | } 117 | } 118 | } 119 | if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */ 120 | medium: 121 | /* rint(x/(pi/2)) */ 122 | fn = (double_t)x*invpio2 + toint - toint; 123 | n = (int32_t)fn; 124 | r = x - fn*pio2_1; 125 | w = fn*pio2_1t; /* 1st round, good to 85 bits */ 126 | /* Matters with directed rounding. */ 127 | if (predict_false(r - w < -pio4)) { 128 | n--; 129 | fn--; 130 | r = x - fn*pio2_1; 131 | w = fn*pio2_1t; 132 | } else if (predict_false(r - w > pio4)) { 133 | n++; 134 | fn++; 135 | r = x - fn*pio2_1; 136 | w = fn*pio2_1t; 137 | } 138 | y[0] = r - w; 139 | u.f = y[0]; 140 | ey = u.i>>52 & 0x7ff; 141 | ex = ix>>20; 142 | if (ex - ey > 16) { /* 2nd round, good to 118 bits */ 143 | t = r; 144 | w = fn*pio2_2; 145 | r = t - w; 146 | w = fn*pio2_2t - ((t-r)-w); 147 | y[0] = r - w; 148 | u.f = y[0]; 149 | ey = u.i>>52 & 0x7ff; 150 | if (ex - ey > 49) { /* 3rd round, good to 151 bits, covers all cases */ 151 | t = r; 152 | w = fn*pio2_3; 153 | r = t - w; 154 | w = fn*pio2_3t - ((t-r)-w); 155 | y[0] = r - w; 156 | } 157 | } 158 | y[1] = (r - y[0]) - w; 159 | return n; 160 | } 161 | /* 162 | * all other (large) arguments 163 | */ 164 | if (ix >= 0x7ff00000) { /* x is inf or NaN */ 165 | y[0] = y[1] = x - x; 166 | return 0; 167 | } 168 | /* set z = scalbn(|x|,-ilogb(x)+23) */ 169 | u.f = x; 170 | u.i &= (uint64_t)-1>>12; 171 | u.i |= (uint64_t)(0x3ff + 23)<<52; 172 | z = u.f; 173 | for (i=0; i < 2; i++) { 174 | tx[i] = (double)(int32_t)z; 175 | z = (z-tx[i])*0x1p24; 176 | } 177 | tx[i] = z; 178 | /* skip zero terms, first term is non-zero */ 179 | while (tx[i] == 0.0) 180 | i--; 181 | n = __rem_pio2_large(tx,ty,(int)(ix>>20)-(0x3ff+23),i+1,1); 182 | if (sign) { 183 | y[0] = -ty[0]; 184 | y[1] = -ty[1]; 185 | return -n; 186 | } 187 | y[0] = ty[0]; 188 | y[1] = ty[1]; 189 | return n; 190 | } 191 | -------------------------------------------------------------------------------- /libm/__rem_pio2_large.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/k_rem_pio2.c */ 2 | /* 3 | * ==================================================== 4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 5 | * 6 | * Developed at SunSoft, a Sun Microsystems, Inc. business. 7 | * Permission to use, copy, modify, and distribute this 8 | * software is freely granted, provided that this notice 9 | * is preserved. 10 | * ==================================================== 11 | */ 12 | /* 13 | * __rem_pio2_large(x,y,e0,nx,prec) 14 | * double x[],y[]; int e0,nx,prec; 15 | * 16 | * __rem_pio2_large return the last three digits of N with 17 | * y = x - N*pi/2 18 | * so that |y| < pi/2. 19 | * 20 | * The method is to compute the integer (mod 8) and fraction parts of 21 | * (2/pi)*x without doing the full multiplication. In general we 22 | * skip the part of the product that are known to be a huge integer ( 23 | * more accurately, = 0 mod 8 ). Thus the number of operations are 24 | * independent of the exponent of the input. 25 | * 26 | * (2/pi) is represented by an array of 24-bit integers in ipio2[]. 27 | * 28 | * Input parameters: 29 | * x[] The input value (must be positive) is broken into nx 30 | * pieces of 24-bit integers in double precision format. 31 | * x[i] will be the i-th 24 bit of x. The scaled exponent 32 | * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0 33 | * match x's up to 24 bits. 34 | * 35 | * Example of breaking a double positive z into x[0]+x[1]+x[2]: 36 | * e0 = ilogb(z)-23 37 | * z = scalbn(z,-e0) 38 | * for i = 0,1,2 39 | * x[i] = floor(z) 40 | * z = (z-x[i])*2**24 41 | * 42 | * 43 | * y[] ouput result in an array of double precision numbers. 44 | * The dimension of y[] is: 45 | * 24-bit precision 1 46 | * 53-bit precision 2 47 | * 64-bit precision 2 48 | * 113-bit precision 3 49 | * The actual value is the sum of them. Thus for 113-bit 50 | * precison, one may have to do something like: 51 | * 52 | * long double t,w,r_head, r_tail; 53 | * t = (long double)y[2] + (long double)y[1]; 54 | * w = (long double)y[0]; 55 | * r_head = t+w; 56 | * r_tail = w - (r_head - t); 57 | * 58 | * e0 The exponent of x[0]. Must be <= 16360 or you need to 59 | * expand the ipio2 table. 60 | * 61 | * nx dimension of x[] 62 | * 63 | * prec an integer indicating the precision: 64 | * 0 24 bits (single) 65 | * 1 53 bits (double) 66 | * 2 64 bits (extended) 67 | * 3 113 bits (quad) 68 | * 69 | * External function: 70 | * double scalbn(), floor(); 71 | * 72 | * 73 | * Here is the description of some local variables: 74 | * 75 | * jk jk+1 is the initial number of terms of ipio2[] needed 76 | * in the computation. The minimum and recommended value 77 | * for jk is 3,4,4,6 for single, double, extended, and quad. 78 | * jk+1 must be 2 larger than you might expect so that our 79 | * recomputation test works. (Up to 24 bits in the integer 80 | * part (the 24 bits of it that we compute) and 23 bits in 81 | * the fraction part may be lost to cancelation before we 82 | * recompute.) 83 | * 84 | * jz local integer variable indicating the number of 85 | * terms of ipio2[] used. 86 | * 87 | * jx nx - 1 88 | * 89 | * jv index for pointing to the suitable ipio2[] for the 90 | * computation. In general, we want 91 | * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8 92 | * is an integer. Thus 93 | * e0-3-24*jv >= 0 or (e0-3)/24 >= jv 94 | * Hence jv = max(0,(e0-3)/24). 95 | * 96 | * jp jp+1 is the number of terms in PIo2[] needed, jp = jk. 97 | * 98 | * q[] double array with integral value, representing the 99 | * 24-bits chunk of the product of x and 2/pi. 100 | * 101 | * q0 the corresponding exponent of q[0]. Note that the 102 | * exponent for q[i] would be q0-24*i. 103 | * 104 | * PIo2[] double precision array, obtained by cutting pi/2 105 | * into 24 bits chunks. 106 | * 107 | * f[] ipio2[] in floating point 108 | * 109 | * iq[] integer array by breaking up q[] in 24-bits chunk. 110 | * 111 | * fq[] final product of x*(2/pi) in fq[0],..,fq[jk] 112 | * 113 | * ih integer. If >0 it indicates q[] is >= 0.5, hence 114 | * it also indicates the *sign* of the result. 115 | * 116 | */ 117 | /* 118 | * Constants: 119 | * The hexadecimal values are the intended ones for the following 120 | * constants. The decimal values may be used, provided that the 121 | * compiler will convert from decimal to binary accurately enough 122 | * to produce the hexadecimal values shown. 123 | */ 124 | 125 | #include "libm.h" 126 | 127 | static const int init_jk[] = {3,4,4,6}; /* initial value for jk */ 128 | 129 | /* 130 | * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi 131 | * 132 | * integer array, contains the (24*i)-th to (24*i+23)-th 133 | * bit of 2/pi after binary point. The corresponding 134 | * floating value is 135 | * 136 | * ipio2[i] * 2^(-24(i+1)). 137 | * 138 | * NB: This table must have at least (e0-3)/24 + jk terms. 139 | * For quad precision (e0 <= 16360, jk = 6), this is 686. 140 | */ 141 | static const int32_t ipio2[] = { 142 | 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 143 | 0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, 144 | 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, 145 | 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, 146 | 0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, 147 | 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, 148 | 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, 149 | 0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, 150 | 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, 151 | 0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 152 | 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, 153 | 154 | #if LDBL_MAX_EXP > 1024 155 | 0x47C419, 0xC367CD, 0xDCE809, 0x2A8359, 0xC4768B, 0x961CA6, 156 | 0xDDAF44, 0xD15719, 0x053EA5, 0xFF0705, 0x3F7E33, 0xE832C2, 157 | 0xDE4F98, 0x327DBB, 0xC33D26, 0xEF6B1E, 0x5EF89F, 0x3A1F35, 158 | 0xCAF27F, 0x1D87F1, 0x21907C, 0x7C246A, 0xFA6ED5, 0x772D30, 159 | 0x433B15, 0xC614B5, 0x9D19C3, 0xC2C4AD, 0x414D2C, 0x5D000C, 160 | 0x467D86, 0x2D71E3, 0x9AC69B, 0x006233, 0x7CD2B4, 0x97A7B4, 161 | 0xD55537, 0xF63ED7, 0x1810A3, 0xFC764D, 0x2A9D64, 0xABD770, 162 | 0xF87C63, 0x57B07A, 0xE71517, 0x5649C0, 0xD9D63B, 0x3884A7, 163 | 0xCB2324, 0x778AD6, 0x23545A, 0xB91F00, 0x1B0AF1, 0xDFCE19, 164 | 0xFF319F, 0x6A1E66, 0x615799, 0x47FBAC, 0xD87F7E, 0xB76522, 165 | 0x89E832, 0x60BFE6, 0xCDC4EF, 0x09366C, 0xD43F5D, 0xD7DE16, 166 | 0xDE3B58, 0x929BDE, 0x2822D2, 0xE88628, 0x4D58E2, 0x32CAC6, 167 | 0x16E308, 0xCB7DE0, 0x50C017, 0xA71DF3, 0x5BE018, 0x34132E, 168 | 0x621283, 0x014883, 0x5B8EF5, 0x7FB0AD, 0xF2E91E, 0x434A48, 169 | 0xD36710, 0xD8DDAA, 0x425FAE, 0xCE616A, 0xA4280A, 0xB499D3, 170 | 0xF2A606, 0x7F775C, 0x83C2A3, 0x883C61, 0x78738A, 0x5A8CAF, 171 | 0xBDD76F, 0x63A62D, 0xCBBFF4, 0xEF818D, 0x67C126, 0x45CA55, 172 | 0x36D9CA, 0xD2A828, 0x8D61C2, 0x77C912, 0x142604, 0x9B4612, 173 | 0xC459C4, 0x44C5C8, 0x91B24D, 0xF31700, 0xAD43D4, 0xE54929, 174 | 0x10D5FD, 0xFCBE00, 0xCC941E, 0xEECE70, 0xF53E13, 0x80F1EC, 175 | 0xC3E7B3, 0x28F8C7, 0x940593, 0x3E71C1, 0xB3092E, 0xF3450B, 176 | 0x9C1288, 0x7B20AB, 0x9FB52E, 0xC29247, 0x2F327B, 0x6D550C, 177 | 0x90A772, 0x1FE76B, 0x96CB31, 0x4A1679, 0xE27941, 0x89DFF4, 178 | 0x9794E8, 0x84E6E2, 0x973199, 0x6BED88, 0x365F5F, 0x0EFDBB, 179 | 0xB49A48, 0x6CA467, 0x427271, 0x325D8D, 0xB8159F, 0x09E5BC, 180 | 0x25318D, 0x3974F7, 0x1C0530, 0x010C0D, 0x68084B, 0x58EE2C, 181 | 0x90AA47, 0x02E774, 0x24D6BD, 0xA67DF7, 0x72486E, 0xEF169F, 182 | 0xA6948E, 0xF691B4, 0x5153D1, 0xF20ACF, 0x339820, 0x7E4BF5, 183 | 0x6863B2, 0x5F3EDD, 0x035D40, 0x7F8985, 0x295255, 0xC06437, 184 | 0x10D86D, 0x324832, 0x754C5B, 0xD4714E, 0x6E5445, 0xC1090B, 185 | 0x69F52A, 0xD56614, 0x9D0727, 0x50045D, 0xDB3BB4, 0xC576EA, 186 | 0x17F987, 0x7D6B49, 0xBA271D, 0x296996, 0xACCCC6, 0x5414AD, 187 | 0x6AE290, 0x89D988, 0x50722C, 0xBEA404, 0x940777, 0x7030F3, 188 | 0x27FC00, 0xA871EA, 0x49C266, 0x3DE064, 0x83DD97, 0x973FA3, 189 | 0xFD9443, 0x8C860D, 0xDE4131, 0x9D3992, 0x8C70DD, 0xE7B717, 190 | 0x3BDF08, 0x2B3715, 0xA0805C, 0x93805A, 0x921110, 0xD8E80F, 191 | 0xAF806C, 0x4BFFDB, 0x0F9038, 0x761859, 0x15A562, 0xBBCB61, 192 | 0xB989C7, 0xBD4010, 0x04F2D2, 0x277549, 0xF6B6EB, 0xBB22DB, 193 | 0xAA140A, 0x2F2689, 0x768364, 0x333B09, 0x1A940E, 0xAA3A51, 194 | 0xC2A31D, 0xAEEDAF, 0x12265C, 0x4DC26D, 0x9C7A2D, 0x9756C0, 195 | 0x833F03, 0xF6F009, 0x8C402B, 0x99316D, 0x07B439, 0x15200C, 196 | 0x5BC3D8, 0xC492F5, 0x4BADC6, 0xA5CA4E, 0xCD37A7, 0x36A9E6, 197 | 0x9492AB, 0x6842DD, 0xDE6319, 0xEF8C76, 0x528B68, 0x37DBFC, 198 | 0xABA1AE, 0x3115DF, 0xA1AE00, 0xDAFB0C, 0x664D64, 0xB705ED, 199 | 0x306529, 0xBF5657, 0x3AFF47, 0xB9F96A, 0xF3BE75, 0xDF9328, 200 | 0x3080AB, 0xF68C66, 0x15CB04, 0x0622FA, 0x1DE4D9, 0xA4B33D, 201 | 0x8F1B57, 0x09CD36, 0xE9424E, 0xA4BE13, 0xB52333, 0x1AAAF0, 202 | 0xA8654F, 0xA5C1D2, 0x0F3F0B, 0xCD785B, 0x76F923, 0x048B7B, 203 | 0x721789, 0x53A6C6, 0xE26E6F, 0x00EBEF, 0x584A9B, 0xB7DAC4, 204 | 0xBA66AA, 0xCFCF76, 0x1D02D1, 0x2DF1B1, 0xC1998C, 0x77ADC3, 205 | 0xDA4886, 0xA05DF7, 0xF480C6, 0x2FF0AC, 0x9AECDD, 0xBC5C3F, 206 | 0x6DDED0, 0x1FC790, 0xB6DB2A, 0x3A25A3, 0x9AAF00, 0x9353AD, 207 | 0x0457B6, 0xB42D29, 0x7E804B, 0xA707DA, 0x0EAA76, 0xA1597B, 208 | 0x2A1216, 0x2DB7DC, 0xFDE5FA, 0xFEDB89, 0xFDBE89, 0x6C76E4, 209 | 0xFCA906, 0x70803E, 0x156E85, 0xFF87FD, 0x073E28, 0x336761, 210 | 0x86182A, 0xEABD4D, 0xAFE7B3, 0x6E6D8F, 0x396795, 0x5BBF31, 211 | 0x48D784, 0x16DF30, 0x432DC7, 0x356125, 0xCE70C9, 0xB8CB30, 212 | 0xFD6CBF, 0xA200A4, 0xE46C05, 0xA0DD5A, 0x476F21, 0xD21262, 213 | 0x845CB9, 0x496170, 0xE0566B, 0x015299, 0x375550, 0xB7D51E, 214 | 0xC4F133, 0x5F6E13, 0xE4305D, 0xA92E85, 0xC3B21D, 0x3632A1, 215 | 0xA4B708, 0xD4B1EA, 0x21F716, 0xE4698F, 0x77FF27, 0x80030C, 216 | 0x2D408D, 0xA0CD4F, 0x99A520, 0xD3A2B3, 0x0A5D2F, 0x42F9B4, 217 | 0xCBDA11, 0xD0BE7D, 0xC1DB9B, 0xBD17AB, 0x81A2CA, 0x5C6A08, 218 | 0x17552E, 0x550027, 0xF0147F, 0x8607E1, 0x640B14, 0x8D4196, 219 | 0xDEBE87, 0x2AFDDA, 0xB6256B, 0x34897B, 0xFEF305, 0x9EBFB9, 220 | 0x4F6A68, 0xA82A4A, 0x5AC44F, 0xBCF82D, 0x985AD7, 0x95C7F4, 221 | 0x8D4D0D, 0xA63A20, 0x5F57A4, 0xB13F14, 0x953880, 0x0120CC, 222 | 0x86DD71, 0xB6DEC9, 0xF560BF, 0x11654D, 0x6B0701, 0xACB08C, 223 | 0xD0C0B2, 0x485551, 0x0EFB1E, 0xC37295, 0x3B06A3, 0x3540C0, 224 | 0x7BDC06, 0xCC45E0, 0xFA294E, 0xC8CAD6, 0x41F3E8, 0xDE647C, 225 | 0xD8649B, 0x31BED9, 0xC397A4, 0xD45877, 0xC5E369, 0x13DAF0, 226 | 0x3C3ABA, 0x461846, 0x5F7555, 0xF5BDD2, 0xC6926E, 0x5D2EAC, 227 | 0xED440E, 0x423E1C, 0x87C461, 0xE9FD29, 0xF3D6E7, 0xCA7C22, 228 | 0x35916F, 0xC5E008, 0x8DD7FF, 0xE26A6E, 0xC6FDB0, 0xC10893, 229 | 0x745D7C, 0xB2AD6B, 0x9D6ECD, 0x7B723E, 0x6A11C6, 0xA9CFF7, 230 | 0xDF7329, 0xBAC9B5, 0x5100B7, 0x0DB2E2, 0x24BA74, 0x607DE5, 231 | 0x8AD874, 0x2C150D, 0x0C1881, 0x94667E, 0x162901, 0x767A9F, 232 | 0xBEFDFD, 0xEF4556, 0x367ED9, 0x13D9EC, 0xB9BA8B, 0xFC97C4, 233 | 0x27A831, 0xC36EF1, 0x36C594, 0x56A8D8, 0xB5A8B4, 0x0ECCCF, 234 | 0x2D8912, 0x34576F, 0x89562C, 0xE3CE99, 0xB920D6, 0xAA5E6B, 235 | 0x9C2A3E, 0xCC5F11, 0x4A0BFD, 0xFBF4E1, 0x6D3B8E, 0x2C86E2, 236 | 0x84D4E9, 0xA9B4FC, 0xD1EEEF, 0xC9352E, 0x61392F, 0x442138, 237 | 0xC8D91B, 0x0AFC81, 0x6A4AFB, 0xD81C2F, 0x84B453, 0x8C994E, 238 | 0xCC2254, 0xDC552A, 0xD6C6C0, 0x96190B, 0xB8701A, 0x649569, 239 | 0x605A26, 0xEE523F, 0x0F117F, 0x11B5F4, 0xF5CBFC, 0x2DBC34, 240 | 0xEEBC34, 0xCC5DE8, 0x605EDD, 0x9B8E67, 0xEF3392, 0xB817C9, 241 | 0x9B5861, 0xBC57E1, 0xC68351, 0x103ED8, 0x4871DD, 0xDD1C2D, 242 | 0xA118AF, 0x462C21, 0xD7F359, 0x987AD9, 0xC0549E, 0xFA864F, 243 | 0xFC0656, 0xAE79E5, 0x362289, 0x22AD38, 0xDC9367, 0xAAE855, 244 | 0x382682, 0x9BE7CA, 0xA40D51, 0xB13399, 0x0ED7A9, 0x480569, 245 | 0xF0B265, 0xA7887F, 0x974C88, 0x36D1F9, 0xB39221, 0x4A827B, 246 | 0x21CF98, 0xDC9F40, 0x5547DC, 0x3A74E1, 0x42EB67, 0xDF9DFE, 247 | 0x5FD45E, 0xA4677B, 0x7AACBA, 0xA2F655, 0x23882B, 0x55BA41, 248 | 0x086E59, 0x862A21, 0x834739, 0xE6E389, 0xD49EE5, 0x40FB49, 249 | 0xE956FF, 0xCA0F1C, 0x8A59C5, 0x2BFA94, 0xC5C1D3, 0xCFC50F, 250 | 0xAE5ADB, 0x86C547, 0x624385, 0x3B8621, 0x94792C, 0x876110, 251 | 0x7B4C2A, 0x1A2C80, 0x12BF43, 0x902688, 0x893C78, 0xE4C4A8, 252 | 0x7BDBE5, 0xC23AC4, 0xEAF426, 0x8A67F7, 0xBF920D, 0x2BA365, 253 | 0xB1933D, 0x0B7CBD, 0xDC51A4, 0x63DD27, 0xDDE169, 0x19949A, 254 | 0x9529A8, 0x28CE68, 0xB4ED09, 0x209F44, 0xCA984E, 0x638270, 255 | 0x237C7E, 0x32B90F, 0x8EF5A7, 0xE75614, 0x08F121, 0x2A9DB5, 256 | 0x4D7E6F, 0x5119A5, 0xABF9B5, 0xD6DF82, 0x61DD96, 0x023616, 257 | 0x9F3AC4, 0xA1A283, 0x6DED72, 0x7A8D39, 0xA9B882, 0x5C326B, 258 | 0x5B2746, 0xED3400, 0x7700D2, 0x55F4FC, 0x4D5901, 0x8071E0, 259 | #endif 260 | }; 261 | 262 | static const double PIo2[] = { 263 | 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ 264 | 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ 265 | 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ 266 | 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */ 267 | 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */ 268 | 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */ 269 | 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */ 270 | 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ 271 | }; 272 | 273 | int __rem_pio2_large(double *x, double *y, int e0, int nx, int prec) 274 | { 275 | int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; 276 | double z,fw,f[20],fq[20],q[20]; 277 | 278 | /* initialize jk*/ 279 | jk = init_jk[prec]; 280 | jp = jk; 281 | 282 | /* determine jx,jv,q0, note that 3>q0 */ 283 | jx = nx-1; 284 | jv = (e0-3)/24; if(jv<0) jv=0; 285 | q0 = e0-24*(jv+1); 286 | 287 | /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ 288 | j = jv-jx; m = jx+jk; 289 | for (i=0; i<=m; i++,j++) 290 | f[i] = j<0 ? 0.0 : (double)ipio2[j]; 291 | 292 | /* compute q[0],q[1],...q[jk] */ 293 | for (i=0; i<=jk; i++) { 294 | for (j=0,fw=0.0; j<=jx; j++) 295 | fw += x[j]*f[jx+i-j]; 296 | q[i] = fw; 297 | } 298 | 299 | jz = jk; 300 | recompute: 301 | /* distill q[] into iq[] reversingly */ 302 | for (i=0,j=jz,z=q[jz]; j>0; i++,j--) { 303 | fw = (double)(int32_t)(0x1p-24*z); 304 | iq[i] = (int32_t)(z - 0x1p24*fw); 305 | z = q[j-1]+fw; 306 | } 307 | 308 | /* compute n */ 309 | z = scalbn(z,q0); /* actual value of z */ 310 | z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */ 311 | n = (int32_t)z; 312 | z -= (double)n; 313 | ih = 0; 314 | if (q0 > 0) { /* need iq[jz-1] to determine n */ 315 | i = iq[jz-1]>>(24-q0); n += i; 316 | iq[jz-1] -= i<<(24-q0); 317 | ih = iq[jz-1]>>(23-q0); 318 | } 319 | else if (q0 == 0) ih = iq[jz-1]>>23; 320 | else if (z >= 0.5) ih = 2; 321 | 322 | if (ih > 0) { /* q > 0.5 */ 323 | n += 1; carry = 0; 324 | for (i=0; i 0) { /* rare case: chance is 1 in 12 */ 335 | switch(q0) { 336 | case 1: 337 | iq[jz-1] &= 0x7fffff; break; 338 | case 2: 339 | iq[jz-1] &= 0x3fffff; break; 340 | } 341 | } 342 | if (ih == 2) { 343 | z = 1.0 - z; 344 | if (carry != 0) 345 | z -= scalbn(1.0,q0); 346 | } 347 | } 348 | 349 | /* check if recomputation is needed */ 350 | if (z == 0.0) { 351 | j = 0; 352 | for (i=jz-1; i>=jk; i--) j |= iq[i]; 353 | if (j == 0) { /* need recomputation */ 354 | for (k=1; iq[jk-k]==0; k++); /* k = no. of terms needed */ 355 | 356 | for (i=jz+1; i<=jz+k; i++) { /* add q[jz+1] to q[jz+k] */ 357 | f[jx+i] = (double)ipio2[jv+i]; 358 | for (j=0,fw=0.0; j<=jx; j++) 359 | fw += x[j]*f[jx+i-j]; 360 | q[i] = fw; 361 | } 362 | jz += k; 363 | goto recompute; 364 | } 365 | } 366 | 367 | /* chop off zero terms */ 368 | if (z == 0.0) { 369 | jz -= 1; 370 | q0 -= 24; 371 | while (iq[jz] == 0) { 372 | jz--; 373 | q0 -= 24; 374 | } 375 | } else { /* break z into 24-bit if necessary */ 376 | z = scalbn(z,-q0); 377 | if (z >= 0x1p24) { 378 | fw = (double)(int32_t)(0x1p-24*z); 379 | iq[jz] = (int32_t)(z - 0x1p24*fw); 380 | jz += 1; 381 | q0 += 24; 382 | iq[jz] = (int32_t)fw; 383 | } else 384 | iq[jz] = (int32_t)z; 385 | } 386 | 387 | /* convert integer "bit" chunk to floating-point value */ 388 | fw = scalbn(1.0,q0); 389 | for (i=jz; i>=0; i--) { 390 | q[i] = fw*(double)iq[i]; 391 | fw *= 0x1p-24; 392 | } 393 | 394 | /* compute PIo2[0,...,jp]*q[jz,...,0] */ 395 | for(i=jz; i>=0; i--) { 396 | for (fw=0.0,k=0; k<=jp && k<=jz-i; k++) 397 | fw += PIo2[k]*q[i+k]; 398 | fq[jz-i] = fw; 399 | } 400 | 401 | /* compress fq[] into y[] */ 402 | switch(prec) { 403 | case 0: 404 | fw = 0.0; 405 | for (i=jz; i>=0; i--) 406 | fw += fq[i]; 407 | y[0] = ih==0 ? fw : -fw; 408 | break; 409 | case 1: 410 | case 2: 411 | fw = 0.0; 412 | for (i=jz; i>=0; i--) 413 | fw += fq[i]; 414 | // TODO: drop excess precision here once double_t is used 415 | fw = (double)fw; 416 | y[0] = ih==0 ? fw : -fw; 417 | fw = fq[0]-fw; 418 | for (i=1; i<=jz; i++) 419 | fw += fq[i]; 420 | y[1] = ih==0 ? fw : -fw; 421 | break; 422 | case 3: /* painful */ 423 | for (i=jz; i>0; i--) { 424 | fw = fq[i-1]+fq[i]; 425 | fq[i] += fq[i-1]-fw; 426 | fq[i-1] = fw; 427 | } 428 | for (i=jz; i>1; i--) { 429 | fw = fq[i-1]+fq[i]; 430 | fq[i] += fq[i-1]-fw; 431 | fq[i-1] = fw; 432 | } 433 | for (fw=0.0,i=jz; i>=2; i--) 434 | fw += fq[i]; 435 | if (ih==0) { 436 | y[0] = fq[0]; y[1] = fq[1]; y[2] = fw; 437 | } else { 438 | y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw; 439 | } 440 | } 441 | return n&7; 442 | } 443 | -------------------------------------------------------------------------------- /libm/__sin.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/k_sin.c */ 2 | /* 3 | * ==================================================== 4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 5 | * 6 | * Developed at SunSoft, a Sun Microsystems, Inc. business. 7 | * Permission to use, copy, modify, and distribute this 8 | * software is freely granted, provided that this notice 9 | * is preserved. 10 | * ==================================================== 11 | */ 12 | /* __sin( x, y, iy) 13 | * kernel sin function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854 14 | * Input x is assumed to be bounded by ~pi/4 in magnitude. 15 | * Input y is the tail of x. 16 | * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). 17 | * 18 | * Algorithm 19 | * 1. Since sin(-x) = -sin(x), we need only to consider positive x. 20 | * 2. Callers must return sin(-0) = -0 without calling here since our 21 | * odd polynomial is not evaluated in a way that preserves -0. 22 | * Callers may do the optimization sin(x) ~ x for tiny x. 23 | * 3. sin(x) is approximated by a polynomial of degree 13 on 24 | * [0,pi/4] 25 | * 3 13 26 | * sin(x) ~ x + S1*x + ... + S6*x 27 | * where 28 | * 29 | * |sin(x) 2 4 6 8 10 12 | -58 30 | * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 31 | * | x | 32 | * 33 | * 4. sin(x+y) = sin(x) + sin'(x')*y 34 | * ~ sin(x) + (1-x*x/2)*y 35 | * For better accuracy, let 36 | * 3 2 2 2 2 37 | * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6)))) 38 | * then 3 2 39 | * sin(x) = x + (S1*x + (x *(r-y/2)+y)) 40 | */ 41 | 42 | #include "libm.h" 43 | 44 | static const double 45 | S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ 46 | S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ 47 | S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */ 48 | S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */ 49 | S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ 50 | S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ 51 | 52 | double __sin(double x, double y, int iy) 53 | { 54 | double_t z,r,v,w; 55 | 56 | z = x*x; 57 | w = z*z; 58 | r = S2 + z*(S3 + z*S4) + z*w*(S5 + z*S6); 59 | v = z*x; 60 | if (iy == 0) 61 | return x + v*(S1 + z*r); 62 | else 63 | return x - ((z*(0.5*y - v*r) - y) - v*S1); 64 | } 65 | -------------------------------------------------------------------------------- /libm/cos.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_cos.c */ 2 | /* 3 | * ==================================================== 4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 5 | * 6 | * Developed at SunPro, a Sun Microsystems, Inc. business. 7 | * Permission to use, copy, modify, and distribute this 8 | * software is freely granted, provided that this notice 9 | * is preserved. 10 | * ==================================================== 11 | */ 12 | /* cos(x) 13 | * Return cosine function of x. 14 | * 15 | * kernel function: 16 | * __sin ... sine function on [-pi/4,pi/4] 17 | * __cos ... cosine function on [-pi/4,pi/4] 18 | * __rem_pio2 ... argument reduction routine 19 | * 20 | * Method. 21 | * Let S,C and T denote the sin, cos and tan respectively on 22 | * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 23 | * in [-pi/4 , +pi/4], and let n = k mod 4. 24 | * We have 25 | * 26 | * n sin(x) cos(x) tan(x) 27 | * ---------------------------------------------------------- 28 | * 0 S C T 29 | * 1 C -S -1/T 30 | * 2 -S -C T 31 | * 3 -C S -1/T 32 | * ---------------------------------------------------------- 33 | * 34 | * Special cases: 35 | * Let trig be any of sin, cos, or tan. 36 | * trig(+-INF) is NaN, with signals; 37 | * trig(NaN) is that NaN; 38 | * 39 | * Accuracy: 40 | * TRIG(x) returns trig(x) nearly rounded 41 | */ 42 | 43 | #include "libm.h" 44 | 45 | double cos(double x) 46 | { 47 | double y[2]; 48 | uint32_t ix; 49 | unsigned n; 50 | 51 | GET_HIGH_WORD(ix, x); 52 | ix &= 0x7fffffff; 53 | 54 | /* |x| ~< pi/4 */ 55 | if (ix <= 0x3fe921fb) { 56 | if (ix < 0x3e46a09e) { /* |x| < 2**-27 * sqrt(2) */ 57 | /* raise inexact if x!=0 */ 58 | FORCE_EVAL(x + 0x1p120f); 59 | return 1.0; 60 | } 61 | return __cos(x, 0); 62 | } 63 | 64 | /* cos(Inf or NaN) is NaN */ 65 | if (ix >= 0x7ff00000) 66 | return x-x; 67 | 68 | /* argument reduction */ 69 | n = __rem_pio2(x, y); 70 | switch (n&3) { 71 | case 0: return __cos(y[0], y[1]); 72 | case 1: return -__sin(y[0], y[1], 1); 73 | case 2: return -__cos(y[0], y[1]); 74 | default: 75 | return __sin(y[0], y[1], 1); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /libm/endian.h: -------------------------------------------------------------------------------- 1 | #ifndef _ENDIAN_H 2 | #define _ENDIAN_H 3 | 4 | #include "features.h" 5 | 6 | #define __LITTLE_ENDIAN 1234 7 | #define __BIG_ENDIAN 4321 8 | #define __PDP_ENDIAN 3412 9 | 10 | #if defined(__GNUC__) && defined(__BYTE_ORDER__) 11 | #define __BYTE_ORDER __BYTE_ORDER__ 12 | #else 13 | #include 14 | #endif 15 | 16 | #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) 17 | 18 | #define BIG_ENDIAN __BIG_ENDIAN 19 | #define LITTLE_ENDIAN __LITTLE_ENDIAN 20 | #define PDP_ENDIAN __PDP_ENDIAN 21 | #define BYTE_ORDER __BYTE_ORDER 22 | 23 | #include 24 | 25 | static __inline uint16_t __bswap16(uint16_t __x) 26 | { 27 | return __x<<8 | __x>>8; 28 | } 29 | 30 | static __inline uint32_t __bswap32(uint32_t __x) 31 | { 32 | return __x>>24 | __x>>8&0xff00 | __x<<8&0xff0000 | __x<<24; 33 | } 34 | 35 | static __inline uint64_t __bswap64(uint64_t __x) 36 | { 37 | return __bswap32(__x)+0ULL<<32 | __bswap32(__x>>32); 38 | } 39 | 40 | #if __BYTE_ORDER == __LITTLE_ENDIAN 41 | #define htobe16(x) __bswap16(x) 42 | #define be16toh(x) __bswap16(x) 43 | #define betoh16(x) __bswap16(x) 44 | #define htobe32(x) __bswap32(x) 45 | #define be32toh(x) __bswap32(x) 46 | #define betoh32(x) __bswap32(x) 47 | #define htobe64(x) __bswap64(x) 48 | #define be64toh(x) __bswap64(x) 49 | #define betoh64(x) __bswap64(x) 50 | #define htole16(x) (uint16_t)(x) 51 | #define le16toh(x) (uint16_t)(x) 52 | #define letoh16(x) (uint16_t)(x) 53 | #define htole32(x) (uint32_t)(x) 54 | #define le32toh(x) (uint32_t)(x) 55 | #define letoh32(x) (uint32_t)(x) 56 | #define htole64(x) (uint64_t)(x) 57 | #define le64toh(x) (uint64_t)(x) 58 | #define letoh64(x) (uint64_t)(x) 59 | #else 60 | #define htobe16(x) (uint16_t)(x) 61 | #define be16toh(x) (uint16_t)(x) 62 | #define betoh16(x) (uint16_t)(x) 63 | #define htobe32(x) (uint32_t)(x) 64 | #define be32toh(x) (uint32_t)(x) 65 | #define betoh32(x) (uint32_t)(x) 66 | #define htobe64(x) (uint64_t)(x) 67 | #define be64toh(x) (uint64_t)(x) 68 | #define betoh64(x) (uint64_t)(x) 69 | #define htole16(x) __bswap16(x) 70 | #define le16toh(x) __bswap16(x) 71 | #define letoh16(x) __bswap16(x) 72 | #define htole32(x) __bswap32(x) 73 | #define le32toh(x) __bswap32(x) 74 | #define letoh32(x) __bswap32(x) 75 | #define htole64(x) __bswap64(x) 76 | #define le64toh(x) __bswap64(x) 77 | #define letoh64(x) __bswap64(x) 78 | #endif 79 | 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /libm/exp.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/e_exp.c */ 2 | /* 3 | * ==================================================== 4 | * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. 5 | * 6 | * Permission to use, copy, modify, and distribute this 7 | * software is freely granted, provided that this notice 8 | * is preserved. 9 | * ==================================================== 10 | */ 11 | /* exp(x) 12 | * Returns the exponential of x. 13 | * 14 | * Method 15 | * 1. Argument reduction: 16 | * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658. 17 | * Given x, find r and integer k such that 18 | * 19 | * x = k*ln2 + r, |r| <= 0.5*ln2. 20 | * 21 | * Here r will be represented as r = hi-lo for better 22 | * accuracy. 23 | * 24 | * 2. Approximation of exp(r) by a special rational function on 25 | * the interval [0,0.34658]: 26 | * Write 27 | * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ... 28 | * We use a special Remez algorithm on [0,0.34658] to generate 29 | * a polynomial of degree 5 to approximate R. The maximum error 30 | * of this polynomial approximation is bounded by 2**-59. In 31 | * other words, 32 | * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5 33 | * (where z=r*r, and the values of P1 to P5 are listed below) 34 | * and 35 | * | 5 | -59 36 | * | 2.0+P1*z+...+P5*z - R(z) | <= 2 37 | * | | 38 | * The computation of exp(r) thus becomes 39 | * 2*r 40 | * exp(r) = 1 + ---------- 41 | * R(r) - r 42 | * r*c(r) 43 | * = 1 + r + ----------- (for better accuracy) 44 | * 2 - c(r) 45 | * where 46 | * 2 4 10 47 | * c(r) = r - (P1*r + P2*r + ... + P5*r ). 48 | * 49 | * 3. Scale back to obtain exp(x): 50 | * From step 1, we have 51 | * exp(x) = 2^k * exp(r) 52 | * 53 | * Special cases: 54 | * exp(INF) is INF, exp(NaN) is NaN; 55 | * exp(-INF) is 0, and 56 | * for finite argument, only exp(0)=1 is exact. 57 | * 58 | * Accuracy: 59 | * according to an error analysis, the error is always less than 60 | * 1 ulp (unit in the last place). 61 | * 62 | * Misc. info. 63 | * For IEEE double 64 | * if x > 709.782712893383973096 then exp(x) overflows 65 | * if x < -745.133219101941108420 then exp(x) underflows 66 | */ 67 | 68 | #include "libm.h" 69 | 70 | static const double 71 | half[2] = {0.5,-0.5}, 72 | ln2hi = 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */ 73 | ln2lo = 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */ 74 | invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */ 75 | P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ 76 | P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ 77 | P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ 78 | P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ 79 | P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */ 80 | 81 | double __attribute__((weak)) exp(double x) 82 | { 83 | double_t hi, lo, c, xx, y; 84 | int k, sign; 85 | uint32_t hx; 86 | 87 | GET_HIGH_WORD(hx, x); 88 | sign = hx>>31; 89 | hx &= 0x7fffffff; /* high word of |x| */ 90 | 91 | /* special cases */ 92 | if (hx >= 0x4086232b) { /* if |x| >= 708.39... */ 93 | if (isnan(x)) 94 | return x; 95 | if (x > 709.782712893383973096) { 96 | /* overflow if x!=inf */ 97 | x *= 0x1p1023; 98 | return x; 99 | } 100 | if (x < -708.39641853226410622) { 101 | /* underflow if x!=-inf */ 102 | FORCE_EVAL((float)(-0x1p-149/x)); 103 | if (x < -745.13321910194110842) 104 | return 0; 105 | } 106 | } 107 | 108 | /* argument reduction */ 109 | if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ 110 | if (hx >= 0x3ff0a2b2) /* if |x| >= 1.5 ln2 */ 111 | k = (int)(invln2*x + half[sign]); 112 | else 113 | k = 1 - sign - sign; 114 | hi = x - k*ln2hi; /* k*ln2hi is exact here */ 115 | lo = k*ln2lo; 116 | x = hi - lo; 117 | } else if (hx > 0x3e300000) { /* if |x| > 2**-28 */ 118 | k = 0; 119 | hi = x; 120 | lo = 0; 121 | } else { 122 | /* inexact if x!=0 */ 123 | FORCE_EVAL(0x1p1023 + x); 124 | return 1 + x; 125 | } 126 | 127 | /* x is now in primary range */ 128 | xx = x*x; 129 | c = x - xx*(P1+xx*(P2+xx*(P3+xx*(P4+xx*P5)))); 130 | y = 1 + (x*c/(2-c) - lo + hi); 131 | if (k == 0) 132 | return y; 133 | return scalbn(y, k); 134 | } 135 | -------------------------------------------------------------------------------- /libm/features.h: -------------------------------------------------------------------------------- 1 | #ifndef _FEATURES_H 2 | #define _FEATURES_H 3 | 4 | #if defined(_ALL_SOURCE) && !defined(_GNU_SOURCE) 5 | #define _GNU_SOURCE 1 6 | #endif 7 | 8 | #if defined(_DEFAULT_SOURCE) && !defined(_BSD_SOURCE) 9 | #define _BSD_SOURCE 1 10 | #endif 11 | 12 | #if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) \ 13 | && !defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) \ 14 | && !defined(_BSD_SOURCE) && !defined(__STRICT_ANSI__) 15 | #define _BSD_SOURCE 1 16 | #define _XOPEN_SOURCE 700 17 | #endif 18 | 19 | #if __STDC_VERSION__ >= 199901L 20 | #define __restrict restrict 21 | #elif !defined(__GNUC__) 22 | #define __restrict 23 | #endif 24 | 25 | #if __STDC_VERSION__ >= 199901L || defined(__cplusplus) 26 | #define __inline inline 27 | #endif 28 | 29 | #if __STDC_VERSION__ >= 201112L 30 | #elif defined(__GNUC__) 31 | #define _Noreturn __attribute__((__noreturn__)) 32 | #else 33 | #define _Noreturn 34 | #endif 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /libm/floor.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | double __attribute__((weak)) floor(double x) 4 | { 5 | union {double f; uint64_t i;} u = {x}; 6 | int e = u.i >> 52 & 0x7ff; 7 | double_t y; 8 | 9 | if (e >= 0x3ff+52 || x == 0) 10 | return x; 11 | /* y = int(x) - x, where int(x) is an integer neighbor of x */ 12 | if (u.i >> 63) 13 | y = (double)(x - 0x1p52) + 0x1p52 - x; 14 | else 15 | y = (double)(x + 0x1p52) - 0x1p52 - x; 16 | /* special case because of non-nearest rounding modes */ 17 | if (e <= 0x3ff-1) { 18 | FORCE_EVAL(y); 19 | return u.i >> 63 ? -1 : 0; 20 | } 21 | if (y > 0) 22 | return x + y - 1; 23 | return x + y; 24 | } 25 | -------------------------------------------------------------------------------- /libm/fmaxf.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | float fmaxf(float x, float y) 4 | { 5 | if (isnan(x)) 6 | return y; 7 | if (isnan(y)) 8 | return x; 9 | /* handle signed zeroes, see C99 Annex F.9.9.2 */ 10 | if (signbit(x) != signbit(y)) 11 | return signbit(x) ? y : x; 12 | return x < y ? y : x; 13 | } 14 | -------------------------------------------------------------------------------- /libm/fminf.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | float fminf(float x, float y) 4 | { 5 | if (isnan(x)) 6 | return y; 7 | if (isnan(y)) 8 | return x; 9 | /* handle signed zeros, see C99 Annex F.9.9.2 */ 10 | if (signbit(x) != signbit(y)) 11 | return signbit(x) ? x : y; 12 | return x < y ? x : y; 13 | } 14 | -------------------------------------------------------------------------------- /libm/fp_arch.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openmv/tensorflow-lib/9f20a69c2beed44b7cc0cd03f14126eeb0e181d3/libm/fp_arch.h -------------------------------------------------------------------------------- /libm/frexp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | double __attribute__((weak)) frexp(double x, int *e) 5 | { 6 | union { double d; uint64_t i; } y = { x }; 7 | int ee = y.i>>52 & 0x7ff; 8 | 9 | if (!ee) { 10 | if (x) { 11 | x = frexp(x*0x1p64, e); 12 | *e -= 64; 13 | } else *e = 0; 14 | return x; 15 | } else if (ee == 0x7ff) { 16 | return x; 17 | } 18 | 19 | *e = ee - 0x3fe; 20 | y.i &= 0x800fffffffffffffull; 21 | y.i |= 0x3fe0000000000000ull; 22 | return y.d; 23 | } 24 | -------------------------------------------------------------------------------- /libm/libm.h: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/math_private.h */ 2 | /* 3 | * ==================================================== 4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 5 | * 6 | * Developed at SunPro, a Sun Microsystems, Inc. business. 7 | * Permission to use, copy, modify, and distribute this 8 | * software is freely granted, provided that this notice 9 | * is preserved. 10 | * ==================================================== 11 | */ 12 | 13 | #ifndef _LIBM_H 14 | #define _LIBM_H 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include "endian.h" 21 | 22 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 23 | #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN 24 | union ldshape { 25 | long double f; 26 | struct { 27 | uint64_t m; 28 | uint16_t se; 29 | } i; 30 | }; 31 | #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN 32 | union ldshape { 33 | long double f; 34 | struct { 35 | uint64_t lo; 36 | uint32_t mid; 37 | uint16_t top; 38 | uint16_t se; 39 | } i; 40 | struct { 41 | uint64_t lo; 42 | uint64_t hi; 43 | } i2; 44 | }; 45 | #else 46 | #error Unsupported long double representation 47 | #endif 48 | 49 | #define FORCE_EVAL(x) do { \ 50 | if (sizeof(x) == sizeof(float)) { \ 51 | volatile float __x; \ 52 | __x = (x); \ 53 | } else if (sizeof(x) == sizeof(double)) { \ 54 | volatile double __x; \ 55 | __x = (x); \ 56 | } else { \ 57 | volatile long double __x; \ 58 | __x = (x); \ 59 | } \ 60 | } while(0) 61 | 62 | /* Get two 32 bit ints from a double. */ 63 | #define EXTRACT_WORDS(hi,lo,d) \ 64 | do { \ 65 | union {double f; uint64_t i;} __u; \ 66 | __u.f = (d); \ 67 | (hi) = __u.i >> 32; \ 68 | (lo) = (uint32_t)__u.i; \ 69 | } while (0) 70 | 71 | /* Get the more significant 32 bit int from a double. */ 72 | #define GET_HIGH_WORD(hi,d) \ 73 | do { \ 74 | union {double f; uint64_t i;} __u; \ 75 | __u.f = (d); \ 76 | (hi) = __u.i >> 32; \ 77 | } while (0) 78 | 79 | /* Get the less significant 32 bit int from a double. */ 80 | #define GET_LOW_WORD(lo,d) \ 81 | do { \ 82 | union {double f; uint64_t i;} __u; \ 83 | __u.f = (d); \ 84 | (lo) = (uint32_t)__u.i; \ 85 | } while (0) 86 | 87 | /* Set a double from two 32 bit ints. */ 88 | #define INSERT_WORDS(d,hi,lo) \ 89 | do { \ 90 | union {double f; uint64_t i;} __u; \ 91 | __u.i = ((uint64_t)(hi)<<32) | (uint32_t)(lo); \ 92 | (d) = __u.f; \ 93 | } while (0) 94 | 95 | /* Set the more significant 32 bits of a double from an int. */ 96 | #define SET_HIGH_WORD(d,hi) \ 97 | do { \ 98 | union {double f; uint64_t i;} __u; \ 99 | __u.f = (d); \ 100 | __u.i &= 0xffffffff; \ 101 | __u.i |= (uint64_t)(hi) << 32; \ 102 | (d) = __u.f; \ 103 | } while (0) 104 | 105 | /* Set the less significant 32 bits of a double from an int. */ 106 | #define SET_LOW_WORD(d,lo) \ 107 | do { \ 108 | union {double f; uint64_t i;} __u; \ 109 | __u.f = (d); \ 110 | __u.i &= 0xffffffff00000000ull; \ 111 | __u.i |= (uint32_t)(lo); \ 112 | (d) = __u.f; \ 113 | } while (0) 114 | 115 | /* Get a 32 bit int from a float. */ 116 | #define GET_FLOAT_WORD(w,d) \ 117 | do { \ 118 | union {float f; uint32_t i;} __u; \ 119 | __u.f = (d); \ 120 | (w) = __u.i; \ 121 | } while (0) 122 | 123 | /* Set a float from a 32 bit int. */ 124 | #define SET_FLOAT_WORD(d,w) \ 125 | do { \ 126 | union {float f; uint32_t i;} __u; \ 127 | __u.i = (w); \ 128 | (d) = __u.f; \ 129 | } while (0) 130 | 131 | /* fdlibm kernel functions */ 132 | 133 | int __rem_pio2_large(double*,double*,int,int,int); 134 | 135 | int __rem_pio2(double,double*); 136 | double __sin(double,double,int); 137 | double __cos(double,double); 138 | double __tan(double,double,int); 139 | double __expo2(double); 140 | double complex __ldexp_cexp(double complex,int); 141 | 142 | int __rem_pio2f(float,double*); 143 | float __sindf(double); 144 | float __cosdf(double); 145 | float __tandf(double,int); 146 | float __expo2f(float); 147 | float complex __ldexp_cexpf(float complex,int); 148 | 149 | int __rem_pio2l(long double, long double *); 150 | long double __sinl(long double, long double, int); 151 | long double __cosl(long double, long double); 152 | long double __tanl(long double, long double, int); 153 | 154 | /* polynomial evaluation */ 155 | long double __polevll(long double, const long double *, int); 156 | long double __p1evll(long double, const long double *, int); 157 | 158 | #endif 159 | 160 | #ifdef __GNUC__ 161 | #define predict_true(x) __builtin_expect(!!(x), 1) 162 | #define predict_false(x) __builtin_expect(x, 0) 163 | #else 164 | #define predict_true(x) (x) 165 | #define predict_false(x) (x) 166 | #endif 167 | 168 | 169 | -------------------------------------------------------------------------------- /libm/log1p.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_log1p.c */ 2 | /* 3 | * ==================================================== 4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 5 | * 6 | * Developed at SunPro, a Sun Microsystems, Inc. business. 7 | * Permission to use, copy, modify, and distribute this 8 | * software is freely granted, provided that this notice 9 | * is preserved. 10 | * ==================================================== 11 | */ 12 | /* double log1p(double x) 13 | * Return the natural logarithm of 1+x. 14 | * 15 | * Method : 16 | * 1. Argument Reduction: find k and f such that 17 | * 1+x = 2^k * (1+f), 18 | * where sqrt(2)/2 < 1+f < sqrt(2) . 19 | * 20 | * Note. If k=0, then f=x is exact. However, if k!=0, then f 21 | * may not be representable exactly. In that case, a correction 22 | * term is need. Let u=1+x rounded. Let c = (1+x)-u, then 23 | * log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u), 24 | * and add back the correction term c/u. 25 | * (Note: when x > 2**53, one can simply return log(x)) 26 | * 27 | * 2. Approximation of log(1+f): See log.c 28 | * 29 | * 3. Finally, log1p(x) = k*ln2 + log(1+f) + c/u. See log.c 30 | * 31 | * Special cases: 32 | * log1p(x) is NaN with signal if x < -1 (including -INF) ; 33 | * log1p(+INF) is +INF; log1p(-1) is -INF with signal; 34 | * log1p(NaN) is that NaN with no signal. 35 | * 36 | * Accuracy: 37 | * according to an error analysis, the error is always less than 38 | * 1 ulp (unit in the last place). 39 | * 40 | * Constants: 41 | * The hexadecimal values are the intended ones for the following 42 | * constants. The decimal values may be used, provided that the 43 | * compiler will convert from decimal to binary accurately enough 44 | * to produce the hexadecimal values shown. 45 | * 46 | * Note: Assuming log() return accurate answer, the following 47 | * algorithm can be used to compute log1p(x) to within a few ULP: 48 | * 49 | * u = 1+x; 50 | * if(u==1.0) return x ; else 51 | * return log(u)*(x/(u-1.0)); 52 | * 53 | * See HP-15C Advanced Functions Handbook, p.193. 54 | */ 55 | 56 | #include "libm.h" 57 | 58 | static const double 59 | ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ 60 | ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ 61 | Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ 62 | Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ 63 | Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ 64 | Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ 65 | Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ 66 | Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ 67 | Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ 68 | 69 | double log1p(double x) 70 | { 71 | union {double f; uint64_t i;} u = {x}; 72 | double_t hfsq,f,c,s,z,R,w,t1,t2,dk; 73 | uint32_t hx,hu; 74 | int k; 75 | 76 | hx = u.i>>32; 77 | k = 1; 78 | if (hx < 0x3fda827a || hx>>31) { /* 1+x < sqrt(2)+ */ 79 | if (hx >= 0xbff00000) { /* x <= -1.0 */ 80 | if (x == -1) 81 | return x/0.0; /* log1p(-1) = -inf */ 82 | return (x-x)/0.0; /* log1p(x<-1) = NaN */ 83 | } 84 | if (hx<<1 < 0x3ca00000<<1) { /* |x| < 2**-53 */ 85 | /* underflow if subnormal */ 86 | if ((hx&0x7ff00000) == 0) 87 | FORCE_EVAL((float)x); 88 | return x; 89 | } 90 | if (hx <= 0xbfd2bec4) { /* sqrt(2)/2- <= 1+x < sqrt(2)+ */ 91 | k = 0; 92 | c = 0; 93 | f = x; 94 | } 95 | } else if (hx >= 0x7ff00000) 96 | return x; 97 | if (k) { 98 | u.f = 1 + x; 99 | hu = u.i>>32; 100 | hu += 0x3ff00000 - 0x3fe6a09e; 101 | k = (int)(hu>>20) - 0x3ff; 102 | /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */ 103 | if (k < 54) { 104 | c = k >= 2 ? 1-(u.f-x) : x-(u.f-1); 105 | c /= u.f; 106 | } else 107 | c = 0; 108 | /* reduce u into [sqrt(2)/2, sqrt(2)] */ 109 | hu = (hu&0x000fffff) + 0x3fe6a09e; 110 | u.i = (uint64_t)hu<<32 | (u.i&0xffffffff); 111 | f = u.f - 1; 112 | } 113 | hfsq = 0.5*f*f; 114 | s = f/(2.0+f); 115 | z = s*s; 116 | w = z*z; 117 | t1 = w*(Lg2+w*(Lg4+w*Lg6)); 118 | t2 = z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); 119 | R = t2 + t1; 120 | dk = k; 121 | return s*(hfsq+R) + (dk*ln2_lo+c) - hfsq + f + dk*ln2_hi; 122 | } 123 | -------------------------------------------------------------------------------- /libm/round.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | double __attribute__((weak)) round(double x) 4 | { 5 | union {double f; uint64_t i;} u = {x}; 6 | int e = u.i >> 52 & 0x7ff; 7 | double_t y; 8 | 9 | if (e >= 0x3ff+52) 10 | return x; 11 | if (u.i >> 63) 12 | x = -x; 13 | if (e < 0x3ff-1) { 14 | /* raise inexact if x!=0 */ 15 | FORCE_EVAL(x + 0x1p52); 16 | return 0*u.f; 17 | } 18 | y = (double)(x + 0x1p52) - 0x1p52 - x; 19 | if (y > 0.5) 20 | y = y + x - 1; 21 | else if (y <= -0.5) 22 | y = y + x + 1; 23 | else 24 | y = y + x; 25 | if (u.i >> 63) 26 | y = -y; 27 | return y; 28 | } 29 | -------------------------------------------------------------------------------- /libm/scalbn.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | double __attribute__((weak)) scalbn(double x, int n) 5 | { 6 | union {double f; uint64_t i;} u; 7 | double_t y = x; 8 | 9 | if (n > 1023) { 10 | y *= 0x1p1023; 11 | n -= 1023; 12 | if (n > 1023) { 13 | y *= 0x1p1023; 14 | n -= 1023; 15 | if (n > 1023) 16 | n = 1023; 17 | } 18 | } else if (n < -1022) { 19 | y *= 0x1p-1022; 20 | n += 1022; 21 | if (n < -1022) { 22 | y *= 0x1p-1022; 23 | n += 1022; 24 | if (n < -1022) 25 | n = -1022; 26 | } 27 | } 28 | u.i = (uint64_t)(0x3ff+n)<<52; 29 | x = y * u.f; 30 | return x; 31 | } 32 | -------------------------------------------------------------------------------- /libm/sin.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/s_sin.c */ 2 | /* 3 | * ==================================================== 4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 5 | * 6 | * Developed at SunPro, a Sun Microsystems, Inc. business. 7 | * Permission to use, copy, modify, and distribute this 8 | * software is freely granted, provided that this notice 9 | * is preserved. 10 | * ==================================================== 11 | */ 12 | /* sin(x) 13 | * Return sine function of x. 14 | * 15 | * kernel function: 16 | * __sin ... sine function on [-pi/4,pi/4] 17 | * __cos ... cose function on [-pi/4,pi/4] 18 | * __rem_pio2 ... argument reduction routine 19 | * 20 | * Method. 21 | * Let S,C and T denote the sin, cos and tan respectively on 22 | * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 23 | * in [-pi/4 , +pi/4], and let n = k mod 4. 24 | * We have 25 | * 26 | * n sin(x) cos(x) tan(x) 27 | * ---------------------------------------------------------- 28 | * 0 S C T 29 | * 1 C -S -1/T 30 | * 2 -S -C T 31 | * 3 -C S -1/T 32 | * ---------------------------------------------------------- 33 | * 34 | * Special cases: 35 | * Let trig be any of sin, cos, or tan. 36 | * trig(+-INF) is NaN, with signals; 37 | * trig(NaN) is that NaN; 38 | * 39 | * Accuracy: 40 | * TRIG(x) returns trig(x) nearly rounded 41 | */ 42 | 43 | #include "libm.h" 44 | 45 | double sin(double x) 46 | { 47 | double y[2]; 48 | uint32_t ix; 49 | unsigned n; 50 | 51 | /* High word of x. */ 52 | GET_HIGH_WORD(ix, x); 53 | ix &= 0x7fffffff; 54 | 55 | /* |x| ~< pi/4 */ 56 | if (ix <= 0x3fe921fb) { 57 | if (ix < 0x3e500000) { /* |x| < 2**-26 */ 58 | /* raise inexact if x != 0 and underflow if subnormal*/ 59 | FORCE_EVAL(ix < 0x00100000 ? x/0x1p120f : x+0x1p120f); 60 | return x; 61 | } 62 | return __sin(x, 0.0, 0); 63 | } 64 | 65 | /* sin(Inf or NaN) is NaN */ 66 | if (ix >= 0x7ff00000) 67 | return x - x; 68 | 69 | /* argument reduction needed */ 70 | n = __rem_pio2(x, y); 71 | switch (n&3) { 72 | case 0: return __sin(y[0], y[1], 1); 73 | case 1: return __cos(y[0], y[1]); 74 | case 2: return -__sin(y[0], y[1], 1); 75 | default: 76 | return -__cos(y[0], y[1]); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /libm/sqrt.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/e_sqrt.c */ 2 | /* 3 | * ==================================================== 4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 5 | * 6 | * Developed at SunSoft, a Sun Microsystems, Inc. business. 7 | * Permission to use, copy, modify, and distribute this 8 | * software is freely granted, provided that this notice 9 | * is preserved. 10 | * ==================================================== 11 | */ 12 | /* sqrt(x) 13 | * Return correctly rounded sqrt. 14 | * ------------------------------------------ 15 | * | Use the hardware sqrt if you have one | 16 | * ------------------------------------------ 17 | * Method: 18 | * Bit by bit method using integer arithmetic. (Slow, but portable) 19 | * 1. Normalization 20 | * Scale x to y in [1,4) with even powers of 2: 21 | * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then 22 | * sqrt(x) = 2^k * sqrt(y) 23 | * 2. Bit by bit computation 24 | * Let q = sqrt(y) truncated to i bit after binary point (q = 1), 25 | * i 0 26 | * i+1 2 27 | * s = 2*q , and y = 2 * ( y - q ). (1) 28 | * i i i i 29 | * 30 | * To compute q from q , one checks whether 31 | * i+1 i 32 | * 33 | * -(i+1) 2 34 | * (q + 2 ) <= y. (2) 35 | * i 36 | * -(i+1) 37 | * If (2) is false, then q = q ; otherwise q = q + 2 . 38 | * i+1 i i+1 i 39 | * 40 | * With some algebric manipulation, it is not difficult to see 41 | * that (2) is equivalent to 42 | * -(i+1) 43 | * s + 2 <= y (3) 44 | * i i 45 | * 46 | * The advantage of (3) is that s and y can be computed by 47 | * i i 48 | * the following recurrence formula: 49 | * if (3) is false 50 | * 51 | * s = s , y = y ; (4) 52 | * i+1 i i+1 i 53 | * 54 | * otherwise, 55 | * -i -(i+1) 56 | * s = s + 2 , y = y - s - 2 (5) 57 | * i+1 i i+1 i i 58 | * 59 | * One may easily use induction to prove (4) and (5). 60 | * Note. Since the left hand side of (3) contain only i+2 bits, 61 | * it does not necessary to do a full (53-bit) comparison 62 | * in (3). 63 | * 3. Final rounding 64 | * After generating the 53 bits result, we compute one more bit. 65 | * Together with the remainder, we can decide whether the 66 | * result is exact, bigger than 1/2ulp, or less than 1/2ulp 67 | * (it will never equal to 1/2ulp). 68 | * The rounding mode can be detected by checking whether 69 | * huge + tiny is equal to huge, and whether huge - tiny is 70 | * equal to huge for some floating point number "huge" and "tiny". 71 | * 72 | * Special cases: 73 | * sqrt(+-0) = +-0 ... exact 74 | * sqrt(inf) = inf 75 | * sqrt(-ve) = NaN ... with invalid signal 76 | * sqrt(NaN) = NaN ... with invalid signal for signaling NaN 77 | */ 78 | 79 | #include "libm.h" 80 | 81 | static const double tiny = 1.0e-300; 82 | 83 | double sqrt(double x) 84 | { 85 | double z; 86 | int32_t sign = (int)0x80000000; 87 | int32_t ix0,s0,q,m,t,i; 88 | uint32_t r,t1,s1,ix1,q1; 89 | 90 | EXTRACT_WORDS(ix0, ix1, x); 91 | 92 | /* take care of Inf and NaN */ 93 | if ((ix0&0x7ff00000) == 0x7ff00000) { 94 | return x*x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */ 95 | } 96 | /* take care of zero */ 97 | if (ix0 <= 0) { 98 | if (((ix0&~sign)|ix1) == 0) 99 | return x; /* sqrt(+-0) = +-0 */ 100 | if (ix0 < 0) 101 | return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ 102 | } 103 | /* normalize x */ 104 | m = ix0>>20; 105 | if (m == 0) { /* subnormal x */ 106 | while (ix0 == 0) { 107 | m -= 21; 108 | ix0 |= (ix1>>11); 109 | ix1 <<= 21; 110 | } 111 | for (i=0; (ix0&0x00100000) == 0; i++) 112 | ix0<<=1; 113 | m -= i - 1; 114 | ix0 |= ix1>>(32-i); 115 | ix1 <<= i; 116 | } 117 | m -= 1023; /* unbias exponent */ 118 | ix0 = (ix0&0x000fffff)|0x00100000; 119 | if (m & 1) { /* odd m, double x to make it even */ 120 | ix0 += ix0 + ((ix1&sign)>>31); 121 | ix1 += ix1; 122 | } 123 | m >>= 1; /* m = [m/2] */ 124 | 125 | /* generate sqrt(x) bit by bit */ 126 | ix0 += ix0 + ((ix1&sign)>>31); 127 | ix1 += ix1; 128 | q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ 129 | r = 0x00200000; /* r = moving bit from right to left */ 130 | 131 | while (r != 0) { 132 | t = s0 + r; 133 | if (t <= ix0) { 134 | s0 = t + r; 135 | ix0 -= t; 136 | q += r; 137 | } 138 | ix0 += ix0 + ((ix1&sign)>>31); 139 | ix1 += ix1; 140 | r >>= 1; 141 | } 142 | 143 | r = sign; 144 | while (r != 0) { 145 | t1 = s1 + r; 146 | t = s0; 147 | if (t < ix0 || (t == ix0 && t1 <= ix1)) { 148 | s1 = t1 + r; 149 | if ((t1&sign) == sign && (s1&sign) == 0) 150 | s0++; 151 | ix0 -= t; 152 | if (ix1 < t1) 153 | ix0--; 154 | ix1 -= t1; 155 | q1 += r; 156 | } 157 | ix0 += ix0 + ((ix1&sign)>>31); 158 | ix1 += ix1; 159 | r >>= 1; 160 | } 161 | 162 | /* use floating add to find out rounding direction */ 163 | if ((ix0|ix1) != 0) { 164 | z = 1.0 - tiny; /* raise inexact flag */ 165 | if (z >= 1.0) { 166 | z = 1.0 + tiny; 167 | if (q1 == (uint32_t)0xffffffff) { 168 | q1 = 0; 169 | q++; 170 | } else if (z > 1.0) { 171 | if (q1 == (uint32_t)0xfffffffe) 172 | q++; 173 | q1 += 2; 174 | } else 175 | q1 += q1 & 1; 176 | } 177 | } 178 | ix0 = (q>>1) + 0x3fe00000; 179 | ix1 = q1>>1; 180 | if (q&1) 181 | ix1 |= sign; 182 | INSERT_WORDS(z, ix0 + ((uint32_t)m << 20), ix1); 183 | return z; 184 | } 185 | -------------------------------------------------------------------------------- /libtf.cc: -------------------------------------------------------------------------------- 1 | /* This file is part of the OpenMV project. 2 | * Copyright (c) 2013-2024 Ibrahim Abdelkader & Kwabena W. Agyeman 3 | * This work is licensed under the MIT license, see the file LICENSE for details. 4 | */ 5 | 6 | #include 7 | #include 8 | #include "tensorflow/lite/micro/micro_mutable_op_resolver.h" 9 | #include "tensorflow/lite/micro/cortex_m_generic/debug_log_callback.h" 10 | #include "tensorflow/lite/micro/examples/micro_speech/micro_features/micro_features_generator.h" 11 | #include "tensorflow/lite/micro/micro_interpreter.h" 12 | 13 | #include "libtf.h" 14 | #define LIBTF_MAX_OPS 80 15 | 16 | extern "C" { 17 | // Default log handler. 18 | __attribute__((weak)) void libtf_log_handler(const char *s) { 19 | printf(s); 20 | } 21 | 22 | static int libtf_align_tensor_arena(unsigned char **tensor_arena, size_t *tensor_arena_size) { 23 | size_t alignment = ((size_t) (*tensor_arena)) % LIBTF_TENSOR_ARENA_ALIGNMENT; 24 | 25 | if (alignment) { 26 | size_t fix = LIBTF_TENSOR_ARENA_ALIGNMENT - alignment; 27 | 28 | if ((*tensor_arena_size) < fix) { 29 | return 1; 30 | } 31 | 32 | (*tensor_arena) += fix; 33 | (*tensor_arena_size) -= fix; 34 | } 35 | 36 | return 0; 37 | } 38 | 39 | static bool libtf_valid_dataype(TfLiteType type) { 40 | return (type == kTfLiteUInt8) || (type == kTfLiteInt8) || (type == kTfLiteFloat32); 41 | } 42 | 43 | static libtf_datatype_t libtf_map_datatype(TfLiteType type) { 44 | if (type == kTfLiteUInt8) { 45 | return LIBTF_DATATYPE_UINT8; 46 | } else if (type == kTfLiteInt8) { 47 | return LIBTF_DATATYPE_INT8; 48 | } else { 49 | return LIBTF_DATATYPE_FLOAT; 50 | } 51 | } 52 | 53 | typedef void (*libtf_resolver_init_t) (tflite::MicroMutableOpResolver &); 54 | 55 | static void libtf_init_op_resolver_default(tflite::MicroMutableOpResolver &resolver) { 56 | resolver.AddAbs(); 57 | resolver.AddAdd(); 58 | resolver.AddAddN(); 59 | // resolver.AddArgMax(); 60 | resolver.AddArgMin(); 61 | resolver.AddAveragePool2D(); 62 | // resolver.AddBatchMatMul(); 63 | // resolver.AddBatchToSpaceNd(); 64 | // resolver.AddCast(); 65 | // resolver.AddCeil(); 66 | // resolver.AddCircularBuffer(); - Doesn't compile in OpenMV Cam firmware 67 | // resolver.AddComplexAbs(); 68 | resolver.AddConcatenation(); 69 | resolver.AddConv2D(); 70 | // resolver.AddCos(); 71 | resolver.AddDepthwiseConv2D(); 72 | resolver.AddDequantize(); 73 | // resolver.AddDetectionPostprocess(); - Disabled in library. 74 | // resolver.AddDiv(); 75 | // resolver.AddElu(); 76 | // resolver.AddEqual(); 77 | // resolver.AddEthosU(); - Future. 78 | resolver.AddExp(); 79 | // resolver.AddExpandDims(); 80 | resolver.AddFloor(); 81 | resolver.AddFullyConnected(); 82 | // resolver.AddGather(); - Disabled because of TF_LITE_STATIC_MEMORY 83 | // resolver.AddGreater(); 84 | // resolver.AddGreaterEqual(); 85 | // resolver.AddHardSwish(); 86 | // resolver.AddImag(); 87 | // resolver.AddL2Normalization(); 88 | // resolver.AddL2Pool2D(); 89 | resolver.AddLeakyRelu(); 90 | resolver.AddLess(); 91 | // resolver.AddLessEqual(); 92 | // resolver.AddLog(); 93 | // resolver.AddLogicalAnd(); 94 | // resolver.AddLogicalNot(); 95 | // resolver.AddLogicalOr(); 96 | resolver.AddLogistic(); 97 | resolver.AddMaxPool2D(); 98 | resolver.AddMaximum(); 99 | resolver.AddMean(); 100 | resolver.AddMinimum(); 101 | resolver.AddMul(); 102 | // resolver.AddNeg(); 103 | resolver.AddNotEqual(); 104 | resolver.AddPack(); 105 | resolver.AddPad(); 106 | resolver.AddPadV2(); 107 | // resolver.AddPrelu(); 108 | resolver.AddQuantize(); 109 | // resolver.AddReal(); 110 | // resolver.AddReduceMax(); 111 | // resolver.AddReduceMin(); 112 | resolver.AddRelu(); 113 | resolver.AddRelu6(); 114 | resolver.AddReshape(); 115 | resolver.AddResizeNearestNeighbor(); 116 | // resolver.AddRfft2D(); - Doesn't compile in OpenMV Cam firmware 117 | // resolver.AddRound(); 118 | // resolver.AddRsqrt(); 119 | // resolver.AddSelect(); - Disabled because of TF_LITE_STATIC_MEMORY 120 | // resolver.AddSelectV2(); - Disabled because of TF_LITE_STATIC_MEMORY 121 | resolver.AddShape(); 122 | // resolver.AddSin(); 123 | // resolver.AddSlice(); - Doesn't compile in OpenMV Cam firmware 124 | resolver.AddSoftmax(); 125 | // resolver.AddSpaceToBatchNd(); 126 | // resolver.AddSplit(); 127 | // resolver.AddSplitV(); 128 | resolver.AddSqrt(); 129 | // resolver.AddSquare(); 130 | // resolver.AddSquaredDifference(); 131 | // resolver.AddSqueeze(); 132 | resolver.AddStridedSlice(); 133 | resolver.AddSub(); 134 | // resolver.AddSum(); 135 | // resolver.AddSvdf(); 136 | resolver.AddTanh(); 137 | resolver.AddTranspose(); 138 | resolver.AddTransposeConv(); 139 | resolver.AddUnpack(); 140 | // resolver.AddZerosLike(); 141 | } 142 | 143 | static void libtf_init_op_resolver_fullops(tflite::MicroMutableOpResolver &resolver) { 144 | resolver.AddAbs(); 145 | resolver.AddAdd(); 146 | resolver.AddAddN(); 147 | resolver.AddArgMax(); 148 | resolver.AddArgMin(); 149 | resolver.AddAveragePool2D(); 150 | resolver.AddBatchMatMul(); 151 | resolver.AddBatchToSpaceNd(); 152 | resolver.AddCast(); 153 | resolver.AddCeil(); 154 | // resolver.AddCircularBuffer(); - Doesn't compile in OpenMV Cam firmware 155 | resolver.AddComplexAbs(); 156 | resolver.AddConcatenation(); 157 | resolver.AddConv2D(); 158 | resolver.AddCos(); 159 | resolver.AddDepthwiseConv2D(); 160 | resolver.AddDequantize(); 161 | // resolver.AddDetectionPostprocess(); - Disabled in library. 162 | resolver.AddDiv(); 163 | resolver.AddElu(); 164 | resolver.AddEqual(); 165 | // resolver.AddEthosU(); - Future. 166 | resolver.AddExp(); 167 | resolver.AddExpandDims(); 168 | resolver.AddFloor(); 169 | resolver.AddFullyConnected(); 170 | // resolver.AddGather(); - Disabled because of TF_LITE_STATIC_MEMORY 171 | resolver.AddGreater(); 172 | resolver.AddGreaterEqual(); 173 | resolver.AddHardSwish(); 174 | resolver.AddImag(); 175 | resolver.AddL2Normalization(); 176 | resolver.AddL2Pool2D(); 177 | resolver.AddLeakyRelu(); 178 | resolver.AddLess(); 179 | resolver.AddLessEqual(); 180 | resolver.AddLog(); 181 | resolver.AddLogicalAnd(); 182 | resolver.AddLogicalNot(); 183 | resolver.AddLogicalOr(); 184 | resolver.AddLogistic(); 185 | resolver.AddMaxPool2D(); 186 | resolver.AddMaximum(); 187 | resolver.AddMean(); 188 | resolver.AddMinimum(); 189 | resolver.AddMul(); 190 | resolver.AddNeg(); 191 | resolver.AddNotEqual(); 192 | resolver.AddPack(); 193 | resolver.AddPad(); 194 | resolver.AddPadV2(); 195 | resolver.AddPrelu(); 196 | resolver.AddQuantize(); 197 | resolver.AddReal(); 198 | resolver.AddReduceMax(); 199 | resolver.AddReduceMin(); 200 | resolver.AddRelu(); 201 | resolver.AddRelu6(); 202 | resolver.AddReshape(); 203 | resolver.AddResizeNearestNeighbor(); 204 | // resolver.AddRfft2D(); - Doesn't compile in OpenMV Cam firmware 205 | resolver.AddRound(); 206 | resolver.AddRsqrt(); 207 | // resolver.AddSelect(); - Disabled because of TF_LITE_STATIC_MEMORY 208 | // resolver.AddSelectV2(); - Disabled because of TF_LITE_STATIC_MEMORY 209 | resolver.AddShape(); 210 | resolver.AddSin(); 211 | // resolver.AddSlice(); - Doesn't compile in OpenMV Cam firmware 212 | resolver.AddSoftmax(); 213 | resolver.AddSpaceToBatchNd(); 214 | resolver.AddSplit(); 215 | resolver.AddSplitV(); 216 | resolver.AddSqrt(); 217 | resolver.AddSquare(); 218 | resolver.AddSquaredDifference(); 219 | resolver.AddSqueeze(); 220 | resolver.AddStridedSlice(); 221 | resolver.AddSub(); 222 | resolver.AddSum(); 223 | resolver.AddSvdf(); 224 | resolver.AddTanh(); 225 | resolver.AddTranspose(); 226 | resolver.AddTransposeConv(); 227 | resolver.AddUnpack(); 228 | resolver.AddZerosLike(); 229 | } 230 | 231 | static int libtf_get_parameters(const unsigned char *model_data, 232 | unsigned char *tensor_arena, size_t tensor_arena_size, 233 | libtf_parameters_t *params, 234 | libtf_resolver_init_t libtf_resolver_init) { 235 | RegisterDebugLogCallback(libtf_log_handler); 236 | 237 | tflite::MicroErrorReporter micro_error_reporter; 238 | tflite::ErrorReporter *error_reporter = µ_error_reporter; 239 | 240 | const tflite::Model *model = tflite::GetModel(model_data); 241 | 242 | if (model->version() != TFLITE_SCHEMA_VERSION) { 243 | error_reporter->Report("Model provided is schema version is not equal to supported version!"); 244 | return 1; 245 | } 246 | 247 | if (libtf_align_tensor_arena(&tensor_arena, &tensor_arena_size)) { 248 | error_reporter->Report("Align failed!"); 249 | return 1; 250 | } 251 | 252 | tflite::MicroMutableOpResolver resolver; 253 | libtf_resolver_init(resolver); 254 | 255 | tflite::MicroInterpreter interpreter(model, resolver, tensor_arena, tensor_arena_size, error_reporter); 256 | 257 | if (interpreter.AllocateTensors() != kTfLiteOk) { 258 | error_reporter->Report("AllocateTensors() failed!"); 259 | return 1; 260 | } 261 | 262 | params->tensor_arena_size = interpreter.arena_used_bytes() + 1024; 263 | 264 | // Handle input parameters. 265 | { 266 | TfLiteTensor *model_input = interpreter.input(0); 267 | 268 | if (!libtf_valid_dataype(model_input->type)) { 269 | error_reporter->Report("Input model data type should be 8-bit quantized!"); 270 | return 1; 271 | } 272 | 273 | if (model_input->dims->size == 2) { 274 | 275 | params->input_height = model_input->dims->data[0]; 276 | params->input_width = model_input->dims->data[1]; 277 | params->input_channels = 1; 278 | 279 | } else if (model_input->dims->size == 3) { 280 | 281 | if ((model_input->dims->data[2] != 1) && (model_input->dims->data[2] != 3)) { 282 | error_reporter->Report("Input dimension [c] should be 1 or 3!"); 283 | return 1; 284 | } 285 | 286 | params->input_height = model_input->dims->data[0]; 287 | params->input_width = model_input->dims->data[1]; 288 | params->input_channels = model_input->dims->data[2]; 289 | 290 | } else if (model_input->dims->size == 4) { 291 | 292 | if (model_input->dims->data[0] != 1) { 293 | error_reporter->Report("Input dimension [n] should be 1!"); 294 | return 1; 295 | } 296 | 297 | if ((model_input->dims->data[3] != 1) && (model_input->dims->data[3] != 3)) { 298 | error_reporter->Report("Input dimension [c] should be 1 or 3!"); 299 | return 1; 300 | } 301 | 302 | params->input_height = model_input->dims->data[1]; 303 | params->input_width = model_input->dims->data[2]; 304 | params->input_channels = model_input->dims->data[3]; 305 | 306 | } else { 307 | error_reporter->Report("Input dimensions should be [h][w](c=1), [h][w][c==1||c==3], or [n==1][h][w][c==1||c==3]!"); 308 | return 1; 309 | } 310 | 311 | params->input_datatype = libtf_map_datatype(model_input->type); 312 | params->input_scale = model_input->params.scale; 313 | params->input_zero_point = model_input->params.zero_point; 314 | } 315 | 316 | // Handle output parameters. 317 | { 318 | TfLiteTensor *model_output = interpreter.output(0); 319 | 320 | if (!libtf_valid_dataype(model_output->type)) { 321 | error_reporter->Report("Output model data type should be 8-bit quantized!"); 322 | return 1; 323 | } 324 | 325 | if (model_output->dims->size == 1) { 326 | 327 | params->output_height = 1; 328 | params->output_width = 1; 329 | params->output_channels = model_output->dims->data[0]; 330 | 331 | } else if (model_output->dims->size == 2) { 332 | 333 | if (model_output->dims->data[0] != 1) { 334 | error_reporter->Report("Output dimension [n] should be 1!"); 335 | return 1; 336 | } 337 | 338 | params->output_height = 1; 339 | params->output_width = 1; 340 | params->output_channels = model_output->dims->data[1]; 341 | 342 | } else if (model_output->dims->size == 3) { 343 | 344 | params->output_height = model_output->dims->data[0]; 345 | params->output_width = model_output->dims->data[1]; 346 | params->output_channels = model_output->dims->data[2]; 347 | 348 | } else if (model_output->dims->size == 4) { 349 | 350 | if (model_output->dims->data[0] != 1) { 351 | error_reporter->Report("Output dimension [n] should be 1!"); 352 | return 1; 353 | } 354 | 355 | params->output_height = model_output->dims->data[1]; 356 | params->output_width = model_output->dims->data[2]; 357 | params->output_channels = model_output->dims->data[3]; 358 | 359 | } else { 360 | error_reporter->Report("Output dimensions should be [c], [n==1][c], [h][w][c], or [n==1][h][w][c]!"); 361 | return 1; 362 | } 363 | 364 | params->output_datatype = libtf_map_datatype(model_output->type); 365 | params->output_scale = model_output->params.scale; 366 | params->output_zero_point = model_output->params.zero_point; 367 | } 368 | 369 | return 0; 370 | } 371 | 372 | int libtf_get_parameters_default(const unsigned char *model_data, 373 | unsigned char *tensor_arena, 374 | size_t tensor_arena_size, 375 | libtf_parameters_t *params) { 376 | return libtf_get_parameters(model_data, 377 | tensor_arena, 378 | tensor_arena_size, 379 | params, 380 | libtf_init_op_resolver_default); 381 | } 382 | 383 | int libtf_get_parameters_fullops(const unsigned char *model_data, 384 | unsigned char *tensor_arena, 385 | size_t tensor_arena_size, 386 | libtf_parameters_t *params) { 387 | return libtf_get_parameters(model_data, 388 | tensor_arena, 389 | tensor_arena_size, 390 | params, 391 | libtf_init_op_resolver_fullops); 392 | } 393 | 394 | static int libtf_invoke(const unsigned char *model_data, 395 | unsigned char *tensor_arena, 396 | libtf_parameters_t *params, 397 | libtf_input_data_callback_t input_callback, 398 | void *input_callback_data, 399 | libtf_output_data_callback_t output_callback, 400 | void *output_callback_data, 401 | libtf_resolver_init_t libtf_resolver_init) { 402 | RegisterDebugLogCallback(libtf_log_handler); 403 | 404 | tflite::MicroErrorReporter micro_error_reporter; 405 | tflite::ErrorReporter *error_reporter = µ_error_reporter; 406 | 407 | const tflite::Model *model = tflite::GetModel(model_data); 408 | 409 | if (model->version() != TFLITE_SCHEMA_VERSION) { 410 | error_reporter->Report("Model provided is schema version is not equal to supported version!"); 411 | return 1; 412 | } 413 | 414 | size_t tensor_arena_size = params->tensor_arena_size; 415 | 416 | if (libtf_align_tensor_arena(&tensor_arena, &tensor_arena_size)) { 417 | error_reporter->Report("Align failed!"); 418 | return 1; 419 | } 420 | 421 | tflite::MicroMutableOpResolver resolver; 422 | libtf_resolver_init(resolver); 423 | 424 | tflite::MicroInterpreter interpreter(model, resolver, tensor_arena, tensor_arena_size, error_reporter); 425 | 426 | if (interpreter.AllocateTensors() != kTfLiteOk) { 427 | error_reporter->Report("AllocateTensors() failed!"); 428 | return 1; 429 | } 430 | 431 | input_callback(input_callback_data, interpreter.input(0)->data.data, params); 432 | 433 | if (interpreter.Invoke() != kTfLiteOk) { 434 | error_reporter->Report("Invoke() failed!"); 435 | return 1; 436 | } 437 | 438 | output_callback(output_callback_data, interpreter.output(0)->data.data, params); 439 | 440 | return 0; 441 | } 442 | 443 | int libtf_invoke_default(const unsigned char *model_data, 444 | unsigned char *tensor_arena, 445 | libtf_parameters_t *params, 446 | libtf_input_data_callback_t input_callback, 447 | void *input_callback_data, 448 | libtf_output_data_callback_t output_callback, 449 | void *output_callback_data) { 450 | return libtf_invoke(model_data, 451 | tensor_arena, 452 | params, 453 | input_callback, 454 | input_callback_data, 455 | output_callback, 456 | output_callback_data, 457 | libtf_init_op_resolver_default); 458 | } 459 | 460 | int libtf_invoke_fullops(const unsigned char *model_data, 461 | unsigned char *tensor_arena, 462 | libtf_parameters_t *params, 463 | libtf_input_data_callback_t input_callback, 464 | void *input_callback_data, 465 | libtf_output_data_callback_t output_callback, 466 | void *output_callback_data) { 467 | return libtf_invoke(model_data, 468 | tensor_arena, 469 | params, 470 | input_callback, 471 | input_callback_data, 472 | output_callback, 473 | output_callback_data, 474 | libtf_init_op_resolver_fullops); 475 | } 476 | 477 | int libtf_initialize_micro_features() { 478 | RegisterDebugLogCallback(libtf_log_handler); 479 | 480 | tflite::MicroErrorReporter micro_error_reporter; 481 | tflite::ErrorReporter *error_reporter = µ_error_reporter; 482 | 483 | if (InitializeMicroFeatures(error_reporter) != kTfLiteOk) { 484 | return 1; 485 | } 486 | 487 | return 0; 488 | } 489 | 490 | int libtf_generate_micro_features(const int16_t *input, int input_size, 491 | int output_size, int8_t *output, size_t *num_samples_read) { 492 | RegisterDebugLogCallback(libtf_log_handler); 493 | 494 | tflite::MicroErrorReporter micro_error_reporter; 495 | tflite::ErrorReporter *error_reporter = µ_error_reporter; 496 | 497 | if (GenerateMicroFeatures(error_reporter, input, input_size, 498 | output_size, output, num_samples_read) != kTfLiteOk) { 499 | return 1; 500 | } 501 | 502 | return 0; 503 | } 504 | } 505 | -------------------------------------------------------------------------------- /libtf.h: -------------------------------------------------------------------------------- 1 | /* This file is part of the OpenMV project. 2 | * Copyright (c) 2013-2024 Ibrahim Abdelkader & Kwabena W. Agyeman 3 | * This work is licensed under the MIT license, see the file LICENSE for details. 4 | */ 5 | 6 | #ifndef __LIBTF_H 7 | #define __LIBTF_H 8 | 9 | #define LIBTF_TENSOR_ARENA_ALIGNMENT 16 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | typedef enum libtf_datatype { 16 | LIBTF_DATATYPE_UINT8, 17 | LIBTF_DATATYPE_INT8, 18 | LIBTF_DATATYPE_FLOAT 19 | } libtf_datatype_t; 20 | 21 | typedef struct libtf_parameters { 22 | size_t tensor_arena_size; 23 | size_t input_height, input_width, input_channels; 24 | libtf_datatype_t input_datatype; 25 | float input_scale; 26 | int input_zero_point; 27 | size_t output_height, output_width, output_channels; 28 | libtf_datatype_t output_datatype; 29 | float output_scale; 30 | int output_zero_point; 31 | } libtf_parameters_t; 32 | 33 | // Call this first to get the model parameters. 34 | // Returns 0 on success and 1 on failure. 35 | // Errors are printed to stdout. 36 | int libtf_get_parameters_default(const unsigned char *model_data, // TensorFlow Lite binary model (8-bit quant). 37 | unsigned char *tensor_arena, // As big as you can make it scratch buffer. 38 | size_t tensor_arena_size, // Size of the above scratch buffer. 39 | libtf_parameters_t *params); // Struct to hold model parameters. 40 | 41 | // Call this first to get the model parameters. 42 | // Returns 0 on success and 1 on failure. 43 | // Errors are printed to stdout. 44 | int libtf_get_parameters_fullops(const unsigned char *model_data, // TensorFlow Lite binary model (8-bit quant). 45 | unsigned char *tensor_arena, // As big as you can make it scratch buffer. 46 | size_t tensor_arena_size, // Size of the above scratch buffer. 47 | libtf_parameters_t *params); // Struct to hold model parameters. 48 | 49 | // Callback to populate the model input data byte array (laid out in [height][width][channel] order). 50 | typedef void (*libtf_input_data_callback_t)(void *callback_data, 51 | void *model_input, 52 | libtf_parameters_t *params); 53 | 54 | // Callback to use the model output data byte array (laid out in [height][width][channel] order). 55 | typedef void (*libtf_output_data_callback_t)(void *callback_data, 56 | void *model_output, 57 | libtf_parameters_t *params); 58 | 59 | // Returns 0 on success and 1 on failure. 60 | // Errors are printed to stdout. 61 | int libtf_invoke_default(const unsigned char *model_data, // TensorFlow Lite binary model (8-bit quant). 62 | unsigned char *tensor_arena, // As big as you can make it scratch buffer. 63 | libtf_parameters_t *params, // Struct with model parameters. 64 | libtf_input_data_callback_t input_callback, // Callback to populate the model input data byte array. 65 | void *input_callback_data, // User data structure passed to input callback. 66 | libtf_output_data_callback_t output_callback, // Callback to use the model output data byte array. 67 | void *output_callback_data); // User data structure passed to output callback. 68 | 69 | // Returns 0 on success and 1 on failure. 70 | // Errors are printed to stdout. 71 | int libtf_invoke_fullops(const unsigned char *model_data, // TensorFlow Lite binary model (8-bit quant). 72 | unsigned char *tensor_arena, // As big as you can make it scratch buffer. 73 | libtf_parameters_t *params, // Struct with model parameters. 74 | libtf_input_data_callback_t input_callback, // Callback to populate the model input data byte array. 75 | void *input_callback_data, // User data structure passed to input callback. 76 | libtf_output_data_callback_t output_callback, // Callback to use the model output data byte array. 77 | void *output_callback_data); // User data structure passed to output callback. 78 | 79 | // Returns 0 on success and 1 on failure. 80 | // Errors are printed to stdout. 81 | int libtf_initialize_micro_features(); 82 | 83 | // Returns 0 on success and 1 on failure. 84 | // Errors are printed to stdout. 85 | // Converts audio sample data into a more compact form 86 | // that's appropriate for feeding into a neural network. 87 | int libtf_generate_micro_features(const int16_t *input, // Audio samples 88 | int input_size, // Audio sample size 89 | int output_size, // Slice data size 90 | int8_t *output, // Slice data 91 | size_t *num_samples_read); // Number of samples used 92 | 93 | #ifdef __cplusplus 94 | } 95 | #endif 96 | 97 | #endif // __LIBTF_H 98 | -------------------------------------------------------------------------------- /libtf/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 The TensorFlow Authors. All rights reserved. 2 | 3 | Apache License 4 | Version 2.0, January 2004 5 | http://www.apache.org/licenses/ 6 | 7 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 8 | 9 | 1. Definitions. 10 | 11 | "License" shall mean the terms and conditions for use, reproduction, 12 | and distribution as defined by Sections 1 through 9 of this document. 13 | 14 | "Licensor" shall mean the copyright owner or entity authorized by 15 | the copyright owner that is granting the License. 16 | 17 | "Legal Entity" shall mean the union of the acting entity and all 18 | other entities that control, are controlled by, or are under common 19 | control with that entity. For the purposes of this definition, 20 | "control" means (i) the power, direct or indirect, to cause the 21 | direction or management of such entity, whether by contract or 22 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 23 | outstanding shares, or (iii) beneficial ownership of such entity. 24 | 25 | "You" (or "Your") shall mean an individual or Legal Entity 26 | exercising permissions granted by this License. 27 | 28 | "Source" form shall mean the preferred form for making modifications, 29 | including but not limited to software source code, documentation 30 | source, and configuration files. 31 | 32 | "Object" form shall mean any form resulting from mechanical 33 | transformation or translation of a Source form, including but 34 | not limited to compiled object code, generated documentation, 35 | and conversions to other media types. 36 | 37 | "Work" shall mean the work of authorship, whether in Source or 38 | Object form, made available under the License, as indicated by a 39 | copyright notice that is included in or attached to the work 40 | (an example is provided in the Appendix below). 41 | 42 | "Derivative Works" shall mean any work, whether in Source or Object 43 | form, that is based on (or derived from) the Work and for which the 44 | editorial revisions, annotations, elaborations, or other modifications 45 | represent, as a whole, an original work of authorship. For the purposes 46 | of this License, Derivative Works shall not include works that remain 47 | separable from, or merely link (or bind by name) to the interfaces of, 48 | the Work and Derivative Works thereof. 49 | 50 | "Contribution" shall mean any work of authorship, including 51 | the original version of the Work and any modifications or additions 52 | to that Work or Derivative Works thereof, that is intentionally 53 | submitted to Licensor for inclusion in the Work by the copyright owner 54 | or by an individual or Legal Entity authorized to submit on behalf of 55 | the copyright owner. For the purposes of this definition, "submitted" 56 | means any form of electronic, verbal, or written communication sent 57 | to the Licensor or its representatives, including but not limited to 58 | communication on electronic mailing lists, source code control systems, 59 | and issue tracking systems that are managed by, or on behalf of, the 60 | Licensor for the purpose of discussing and improving the Work, but 61 | excluding communication that is conspicuously marked or otherwise 62 | designated in writing by the copyright owner as "Not a Contribution." 63 | 64 | "Contributor" shall mean Licensor and any individual or Legal Entity 65 | on behalf of whom a Contribution has been received by Licensor and 66 | subsequently incorporated within the Work. 67 | 68 | 2. Grant of Copyright License. Subject to the terms and conditions of 69 | this License, each Contributor hereby grants to You a perpetual, 70 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 71 | copyright license to reproduce, prepare Derivative Works of, 72 | publicly display, publicly perform, sublicense, and distribute the 73 | Work and such Derivative Works in Source or Object form. 74 | 75 | 3. Grant of Patent License. Subject to the terms and conditions of 76 | this License, each Contributor hereby grants to You a perpetual, 77 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 78 | (except as stated in this section) patent license to make, have made, 79 | use, offer to sell, sell, import, and otherwise transfer the Work, 80 | where such license applies only to those patent claims licensable 81 | by such Contributor that are necessarily infringed by their 82 | Contribution(s) alone or by combination of their Contribution(s) 83 | with the Work to which such Contribution(s) was submitted. If You 84 | institute patent litigation against any entity (including a 85 | cross-claim or counterclaim in a lawsuit) alleging that the Work 86 | or a Contribution incorporated within the Work constitutes direct 87 | or contributory patent infringement, then any patent licenses 88 | granted to You under this License for that Work shall terminate 89 | as of the date such litigation is filed. 90 | 91 | 4. Redistribution. You may reproduce and distribute copies of the 92 | Work or Derivative Works thereof in any medium, with or without 93 | modifications, and in Source or Object form, provided that You 94 | meet the following conditions: 95 | 96 | (a) You must give any other recipients of the Work or 97 | Derivative Works a copy of this License; and 98 | 99 | (b) You must cause any modified files to carry prominent notices 100 | stating that You changed the files; and 101 | 102 | (c) You must retain, in the Source form of any Derivative Works 103 | that You distribute, all copyright, patent, trademark, and 104 | attribution notices from the Source form of the Work, 105 | excluding those notices that do not pertain to any part of 106 | the Derivative Works; and 107 | 108 | (d) If the Work includes a "NOTICE" text file as part of its 109 | distribution, then any Derivative Works that You distribute must 110 | include a readable copy of the attribution notices contained 111 | within such NOTICE file, excluding those notices that do not 112 | pertain to any part of the Derivative Works, in at least one 113 | of the following places: within a NOTICE text file distributed 114 | as part of the Derivative Works; within the Source form or 115 | documentation, if provided along with the Derivative Works; or, 116 | within a display generated by the Derivative Works, if and 117 | wherever such third-party notices normally appear. The contents 118 | of the NOTICE file are for informational purposes only and 119 | do not modify the License. You may add Your own attribution 120 | notices within Derivative Works that You distribute, alongside 121 | or as an addendum to the NOTICE text from the Work, provided 122 | that such additional attribution notices cannot be construed 123 | as modifying the License. 124 | 125 | You may add Your own copyright statement to Your modifications and 126 | may provide additional or different license terms and conditions 127 | for use, reproduction, or distribution of Your modifications, or 128 | for any such Derivative Works as a whole, provided Your use, 129 | reproduction, and distribution of the Work otherwise complies with 130 | the conditions stated in this License. 131 | 132 | 5. Submission of Contributions. Unless You explicitly state otherwise, 133 | any Contribution intentionally submitted for inclusion in the Work 134 | by You to the Licensor shall be under the terms and conditions of 135 | this License, without any additional terms or conditions. 136 | Notwithstanding the above, nothing herein shall supersede or modify 137 | the terms of any separate license agreement you may have executed 138 | with Licensor regarding such Contributions. 139 | 140 | 6. Trademarks. This License does not grant permission to use the trade 141 | names, trademarks, service marks, or product names of the Licensor, 142 | except as required for reasonable and customary use in describing the 143 | origin of the Work and reproducing the content of the NOTICE file. 144 | 145 | 7. Disclaimer of Warranty. Unless required by applicable law or 146 | agreed to in writing, Licensor provides the Work (and each 147 | Contributor provides its Contributions) on an "AS IS" BASIS, 148 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 149 | implied, including, without limitation, any warranties or conditions 150 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 151 | PARTICULAR PURPOSE. You are solely responsible for determining the 152 | appropriateness of using or redistributing the Work and assume any 153 | risks associated with Your exercise of permissions under this License. 154 | 155 | 8. Limitation of Liability. In no event and under no legal theory, 156 | whether in tort (including negligence), contract, or otherwise, 157 | unless required by applicable law (such as deliberate and grossly 158 | negligent acts) or agreed to in writing, shall any Contributor be 159 | liable to You for damages, including any direct, indirect, special, 160 | incidental, or consequential damages of any character arising as a 161 | result of this License or out of the use or inability to use the 162 | Work (including but not limited to damages for loss of goodwill, 163 | work stoppage, computer failure or malfunction, or any and all 164 | other commercial damages or losses), even if such Contributor 165 | has been advised of the possibility of such damages. 166 | 167 | 9. Accepting Warranty or Additional Liability. While redistributing 168 | the Work or Derivative Works thereof, You may choose to offer, 169 | and charge a fee for, acceptance of support, warranty, indemnity, 170 | or other liability obligations and/or rights consistent with this 171 | License. However, in accepting such obligations, You may act only 172 | on Your own behalf and on Your sole responsibility, not on behalf 173 | of any other Contributor, and only if You agree to indemnify, 174 | defend, and hold each Contributor harmless for any liability 175 | incurred by, or claims asserted against, such Contributor by reason 176 | of your accepting any such warranty or additional liability. 177 | 178 | END OF TERMS AND CONDITIONS 179 | 180 | APPENDIX: How to apply the Apache License to your work. 181 | 182 | To apply the Apache License to your work, attach the following 183 | boilerplate notice, with the fields enclosed by brackets "[]" 184 | replaced with your own identifying information. (Don't include 185 | the brackets!) The text should be enclosed in the appropriate 186 | comment syntax for the file format. We also recommend that a 187 | file or class name and description of purpose be included on the 188 | same "printed page" as the copyright notice for easier 189 | identification within third-party archives. 190 | 191 | Copyright [yyyy] [name of copyright owner] 192 | 193 | Licensed under the Apache License, Version 2.0 (the "License"); 194 | you may not use this file except in compliance with the License. 195 | You may obtain a copy of the License at 196 | 197 | http://www.apache.org/licenses/LICENSE-2.0 198 | 199 | Unless required by applicable law or agreed to in writing, software 200 | distributed under the License is distributed on an "AS IS" BASIS, 201 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 202 | See the License for the specific language governing permissions and 203 | limitations under the License. 204 | 205 | MIT License 206 | 207 | Copyright (c) 2017-2021 Arm Limited 208 | 209 | Permission is hereby granted, free of charge, to any person obtaining a copy 210 | of this software and associated documentation files (the "Software"), to deal 211 | in the Software without restriction, including without limitation the rights 212 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 213 | copies of the Software, and to permit persons to whom the Software is 214 | furnished to do so, subject to the following conditions: 215 | 216 | The above copyright notice and this permission notice shall be included in all 217 | copies or substantial portions of the Software. 218 | 219 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 220 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 221 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 222 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 223 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 224 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 225 | SOFTWARE. 226 | 227 | LICENSE 228 | 229 | Redistribution and use in source and binary forms, with or without 230 | modification, are permitted provided that the following conditions are met: 231 | 232 | 1. Redistributions of source code must retain the above copyright notice, this 233 | list of conditions and the following disclaimer. 234 | 235 | 2. Redistributions in binary form must reproduce the above copyright notice, 236 | this list of conditions and the following disclaimer in the documentation 237 | and/or other materials provided with the distribution. 238 | 239 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 240 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 241 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 242 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 243 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 244 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 245 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 246 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 247 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 248 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 249 | -------------------------------------------------------------------------------- /libtf/README: -------------------------------------------------------------------------------- 1 | You must link this library to your application with arm-none-eabi-gcc and have implemented putchar(). 2 | -------------------------------------------------------------------------------- /libtf/cortex-m0plus/libtf.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openmv/tensorflow-lib/9f20a69c2beed44b7cc0cd03f14126eeb0e181d3/libtf/cortex-m0plus/libtf.a -------------------------------------------------------------------------------- /libtf/cortex-m4/libtf.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openmv/tensorflow-lib/9f20a69c2beed44b7cc0cd03f14126eeb0e181d3/libtf/cortex-m4/libtf.a -------------------------------------------------------------------------------- /libtf/cortex-m55/libtf.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openmv/tensorflow-lib/9f20a69c2beed44b7cc0cd03f14126eeb0e181d3/libtf/cortex-m55/libtf.a -------------------------------------------------------------------------------- /libtf/cortex-m7/libtf.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openmv/tensorflow-lib/9f20a69c2beed44b7cc0cd03f14126eeb0e181d3/libtf/cortex-m7/libtf.a -------------------------------------------------------------------------------- /libtf/libtf.h: -------------------------------------------------------------------------------- 1 | /* This file is part of the OpenMV project. 2 | * Copyright (c) 2013-2024 Ibrahim Abdelkader & Kwabena W. Agyeman 3 | * This work is licensed under the MIT license, see the file LICENSE for details. 4 | */ 5 | 6 | #ifndef __LIBTF_H 7 | #define __LIBTF_H 8 | 9 | #define LIBTF_TENSOR_ARENA_ALIGNMENT 16 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | typedef enum libtf_datatype { 16 | LIBTF_DATATYPE_UINT8, 17 | LIBTF_DATATYPE_INT8, 18 | LIBTF_DATATYPE_FLOAT 19 | } libtf_datatype_t; 20 | 21 | typedef struct libtf_parameters { 22 | size_t tensor_arena_size; 23 | size_t input_height, input_width, input_channels; 24 | libtf_datatype_t input_datatype; 25 | float input_scale; 26 | int input_zero_point; 27 | size_t output_height, output_width, output_channels; 28 | libtf_datatype_t output_datatype; 29 | float output_scale; 30 | int output_zero_point; 31 | } libtf_parameters_t; 32 | 33 | // Call this first to get the model parameters. 34 | // Returns 0 on success and 1 on failure. 35 | // Errors are printed to stdout. 36 | int libtf_get_parameters_default(const unsigned char *model_data, // TensorFlow Lite binary model (8-bit quant). 37 | unsigned char *tensor_arena, // As big as you can make it scratch buffer. 38 | size_t tensor_arena_size, // Size of the above scratch buffer. 39 | libtf_parameters_t *params); // Struct to hold model parameters. 40 | 41 | // Call this first to get the model parameters. 42 | // Returns 0 on success and 1 on failure. 43 | // Errors are printed to stdout. 44 | int libtf_get_parameters_fullops(const unsigned char *model_data, // TensorFlow Lite binary model (8-bit quant). 45 | unsigned char *tensor_arena, // As big as you can make it scratch buffer. 46 | size_t tensor_arena_size, // Size of the above scratch buffer. 47 | libtf_parameters_t *params); // Struct to hold model parameters. 48 | 49 | // Callback to populate the model input data byte array (laid out in [height][width][channel] order). 50 | typedef void (*libtf_input_data_callback_t)(void *callback_data, 51 | void *model_input, 52 | libtf_parameters_t *params); 53 | 54 | // Callback to use the model output data byte array (laid out in [height][width][channel] order). 55 | typedef void (*libtf_output_data_callback_t)(void *callback_data, 56 | void *model_output, 57 | libtf_parameters_t *params); 58 | 59 | // Returns 0 on success and 1 on failure. 60 | // Errors are printed to stdout. 61 | int libtf_invoke_default(const unsigned char *model_data, // TensorFlow Lite binary model (8-bit quant). 62 | unsigned char *tensor_arena, // As big as you can make it scratch buffer. 63 | libtf_parameters_t *params, // Struct with model parameters. 64 | libtf_input_data_callback_t input_callback, // Callback to populate the model input data byte array. 65 | void *input_callback_data, // User data structure passed to input callback. 66 | libtf_output_data_callback_t output_callback, // Callback to use the model output data byte array. 67 | void *output_callback_data); // User data structure passed to output callback. 68 | 69 | // Returns 0 on success and 1 on failure. 70 | // Errors are printed to stdout. 71 | int libtf_invoke_fullops(const unsigned char *model_data, // TensorFlow Lite binary model (8-bit quant). 72 | unsigned char *tensor_arena, // As big as you can make it scratch buffer. 73 | libtf_parameters_t *params, // Struct with model parameters. 74 | libtf_input_data_callback_t input_callback, // Callback to populate the model input data byte array. 75 | void *input_callback_data, // User data structure passed to input callback. 76 | libtf_output_data_callback_t output_callback, // Callback to use the model output data byte array. 77 | void *output_callback_data); // User data structure passed to output callback. 78 | 79 | // Returns 0 on success and 1 on failure. 80 | // Errors are printed to stdout. 81 | int libtf_initialize_micro_features(); 82 | 83 | // Returns 0 on success and 1 on failure. 84 | // Errors are printed to stdout. 85 | // Converts audio sample data into a more compact form 86 | // that's appropriate for feeding into a neural network. 87 | int libtf_generate_micro_features(const int16_t *input, // Audio samples 88 | int input_size, // Audio sample size 89 | int output_size, // Slice data size 90 | int8_t *output, // Slice data 91 | size_t *num_samples_read); // Number of samples used 92 | 93 | #ifdef __cplusplus 94 | } 95 | #endif 96 | 97 | #endif // __LIBTF_H 98 | -------------------------------------------------------------------------------- /libtf/models/person_detection.tflite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openmv/tensorflow-lib/9f20a69c2beed44b7cc0cd03f14126eeb0e181d3/libtf/models/person_detection.tflite -------------------------------------------------------------------------------- /libtf/models/person_detection.txt: -------------------------------------------------------------------------------- 1 | person 2 | no_person 3 | -------------------------------------------------------------------------------- /make.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # by: Kwabena W. Agyeman - kwagyeman@openmv.io 4 | 5 | import argparse, multiprocessing, os, re, shutil, sys 6 | 7 | TF_TOP = "edge-impulse-sdk" 8 | TF_LITE = "tensorflow/lite" 9 | TF_LITE_MICRO = os.path.join(TF_LITE, "micro") 10 | 11 | TF_TOP_MICRO_PATH = os.path.join(TF_TOP, TF_LITE_MICRO) 12 | TF_TOP_GEN_PATH = os.path.join(TF_TOP_MICRO_PATH, "tools/make/gen") 13 | TF_TOP_EXPERIMENTAL_PATH = os.path.join(TF_TOP, "tensorflow/lite/experimental") 14 | 15 | TF_EXAMPLES_PATH = os.path.join(TF_LITE_MICRO, "examples") 16 | TF_EXAMPLES_MICRO_FEATURES_PATH = os.path.join(TF_EXAMPLES_PATH, "micro_speech/micro_features") 17 | 18 | TF_EXPERIMENTAL_PATH = "tensorflow/lite/experimental" 19 | TF_EXPERIMENTAL_MICROFRONTEND_PATH = os.path.join(TF_EXPERIMENTAL_PATH, "microfrontend") 20 | 21 | TF_TOOLS_PATH = os.path.join(TF_LITE_MICRO, "tools/make") 22 | TF_TOOLS_DOWNLOADS_PATH = os.path.join(TF_TOOLS_PATH, "downloads") 23 | TF_TOOLS_MAKEFILE_PATH = os.path.join(TF_TOOLS_PATH, "Makefile") 24 | 25 | MODEL_NAME = "person_detection" 26 | MODEL_DATA = "tools/make/downloads/person_model_int8/person_detect_model_data.cc" 27 | MODEL_LABELS = "person\nno_person\n" 28 | MAKE_PROJECT = MODEL_NAME + "_int8" 29 | TEST_PROJECT = MODEL_NAME + "_test_int8" 30 | 31 | DEBUG_LOG_CALLBACK = "cortex_m_generic/debug_log_callback.h" 32 | CMSIS_GCC = "tools/make/downloads/cmsis/CMSIS/Core/Include/cmsis_gcc.h" 33 | 34 | def patch_files(dir_path): 35 | for dname, dirs, files in os.walk(dir_path): 36 | for fname in files: 37 | fpath = os.path.join(dname, fname) 38 | with open(fpath) as f: 39 | s = f.read() 40 | s = s.replace("fprintf", "(void)") 41 | with open(fpath, "w") as f: 42 | f.write(s) 43 | 44 | def convert_model(src, dst): 45 | # https://gist.github.com/petewarden/493294425ac522f00ff45342c71939d7 46 | output_data = bytearray() 47 | with open(src, 'r') as file: 48 | for line in file: 49 | values_match = re.match(r"\W*(0x[0-9a-fA-F,x ]+).*", line) 50 | if values_match: 51 | list_text = values_match.group(1) 52 | values_text = filter(None, list_text.split(",")) 53 | values = [int(x, base=16) for x in values_text] 54 | output_data.extend(values) 55 | with open(dst, 'wb') as output_file: 56 | output_file.write(output_data) 57 | 58 | def generate(target, target_arch, __folder__, args, cpus, builddir, libdir, c_flags, cxx_flags): 59 | 60 | print("==============================\n Building Target - " + target + "\n==============================") 61 | 62 | project_folder = os.path.join(TF_TOP_GEN_PATH, "cortex_m_generic_" + target_arch + "_default") 63 | 64 | if (not os.path.isdir(project_folder)) or (not args.skip_generation): 65 | if os.system("cd " + TF_TOP + 66 | " && make -f " + TF_TOOLS_MAKEFILE_PATH + " -j" + str(cpus) + 67 | " TARGET=cortex_m_generic TARGET_ARCH=" + target_arch + 68 | " OPTIMIZED_KERNEL_DIR=cmsis_nn generate_" + MAKE_PROJECT + "_make_project"): 69 | sys.exit("Make Failed...") 70 | 71 | if os.path.exists(os.path.join(builddir, target)): 72 | shutil.rmtree(os.path.join(builddir, target), ignore_errors = True) 73 | 74 | shutil.copytree(project_folder, os.path.join(builddir, target)) 75 | 76 | tflite_micro_project_folder = os.path.join("prj", MAKE_PROJECT, "make") 77 | tflite_micro_gen_folder = "genfiles/tensorflow/lite/micro/models" 78 | 79 | shutil.copytree("libc", os.path.join(builddir, target, tflite_micro_project_folder, "libc")) 80 | shutil.copytree("libm", os.path.join(builddir, target, tflite_micro_project_folder, "libm")) 81 | 82 | shutil.copytree(os.path.join(TF_TOP_MICRO_PATH, "tools/make/downloads/kissfft"), 83 | os.path.join(builddir, target, tflite_micro_project_folder, TF_TOOLS_DOWNLOADS_PATH, "kissfft")) 84 | 85 | shutil.copytree(os.path.join(TF_TOP_EXPERIMENTAL_PATH, "microfrontend"), 86 | os.path.join(builddir, target, tflite_micro_project_folder, TF_EXPERIMENTAL_MICROFRONTEND_PATH)) 87 | 88 | shutil.copytree(os.path.join(TF_TOP_MICRO_PATH, "examples/micro_speech/micro_features"), 89 | os.path.join(builddir, target, tflite_micro_project_folder, TF_EXAMPLES_MICRO_FEATURES_PATH)) 90 | 91 | patch_files(os.path.join(builddir, target, tflite_micro_project_folder, TF_TOOLS_DOWNLOADS_PATH, "kissfft")) 92 | patch_files(os.path.join(builddir, target, tflite_micro_project_folder, TF_EXPERIMENTAL_MICROFRONTEND_PATH)) 93 | patch_files(os.path.join(builddir, target, tflite_micro_project_folder, TF_EXAMPLES_MICRO_FEATURES_PATH)) 94 | 95 | shutil.copyfile(os.path.join(TF_TOP_MICRO_PATH, DEBUG_LOG_CALLBACK), 96 | os.path.join(builddir, target, tflite_micro_project_folder, TF_LITE_MICRO, DEBUG_LOG_CALLBACK)) 97 | 98 | shutil.copyfile(os.path.join(TF_TOP_MICRO_PATH, CMSIS_GCC), 99 | os.path.join(builddir, target, tflite_micro_project_folder, TF_LITE_MICRO, CMSIS_GCC)) 100 | 101 | if os.system("cd " + os.path.join(builddir, target, tflite_micro_project_folder) + 102 | " && git clone https://github.com/edgeimpulse/inferencing-sdk-cpp.git edge-impulse-sdk"): 103 | sys.exit("Make Failed...") 104 | 105 | SRCS = [ 106 | "SRCS :=", 107 | "libtf.cc", 108 | "libc/bsearch.c", 109 | "libm/exp.c", 110 | "libm/floor.c", 111 | "libm/fmaxf.c", 112 | "libm/fminf.c", 113 | "libm/frexp.c", 114 | "libm/round.c", 115 | "libm/sqrt.c", 116 | "libm/scalbn.c", 117 | "libm/cos.c", 118 | "libm/__cos.c", 119 | "libm/sin.c", 120 | "libm/__sin.c", 121 | "libm/log1p.c", 122 | "libm/__rem_pio2.c", 123 | "libm/__rem_pio2_large.c", 124 | os.path.join(TF_TOOLS_DOWNLOADS_PATH, "kissfft/kiss_fft.c"), 125 | os.path.join(TF_TOOLS_DOWNLOADS_PATH, "kissfft/tools/kiss_fftr.c"), 126 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/noise_reduction_io.c"), 127 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/filterbank_io.c"), 128 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/log_scale_util.c"), 129 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/fft_util.cc"), 130 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/log_lut.c"), 131 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/filterbank_util.c"), 132 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/frontend_memmap_generator.c"), 133 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/window.c"), 134 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/pcan_gain_control_util.c"), 135 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/frontend_io.c"), 136 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/frontend.c"), 137 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/window_util.c"), 138 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/fft.cc"), 139 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/log_scale_io.c"), 140 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/filterbank.c"), 141 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/fft_io.c"), 142 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/noise_reduction_util.c"), 143 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/noise_reduction.c"), 144 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/log_scale.c"), 145 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/frontend_util.c"), 146 | os.path.join(TF_EXPERIMENTAL_MICROFRONTEND_PATH, "lib/pcan_gain_control.c"), 147 | os.path.join(TF_EXAMPLES_MICRO_FEATURES_PATH, "micro_features_generator.cc"), 148 | "\\" 149 | ] 150 | 151 | gcc_embedded_folder = os.path.join(__folder__, os.path.join(TF_TOP_MICRO_PATH, "tools/make/downloads/gcc_embedded/bin")) 152 | 153 | arm_none_eabi_gcc = os.path.join(gcc_embedded_folder, "arm-none-eabi-gcc") 154 | arm_none_eabi_ar = os.path.join(gcc_embedded_folder, "arm-none-eabi-ar") 155 | 156 | with open(os.path.join(builddir, target, tflite_micro_project_folder, "Makefile"), 'r') as original: 157 | data = original.read() 158 | data = re.sub(r"TARGET_TOOLCHAIN_ROOT := \S*", "TARGET_TOOLCHAIN_ROOT := " + gcc_embedded_folder + "/", data) 159 | data = data.replace("LIBRARY_OBJS := $(filter-out tensorflow/lite/micro/examples/%, $(OBJS))", "LIBRARY_OBJS := $(OBJS)") 160 | data = re.sub(r" tensorflow/lite/micro/examples/\S*", "", data) 161 | data = re.sub(r" tensorflow/lite/micro/" + MODEL_DATA, "", data) 162 | data = re.sub(r" tensorflow/lite/schema/schema_generated.h", "", data) 163 | data = re.sub(r" tensorflow/lite/micro/kernels/ethosu.cc", "", data) 164 | data = re.sub(r" tensorflow/lite/micro/kernels/tflite_detection_postprocess.cc", "", data) 165 | data = data.replace("SRCS := \\", " ".join(SRCS)) 166 | data = data.replace("-Wall ", " ") 167 | data = data.replace("-Wdouble-promotion ", " ") 168 | data = data.replace("-Wsign-compare ", " ") 169 | data = data.replace("-Wstrict-aliasing ", " ") 170 | data = data.replace("-Wunused-variable ", " ") 171 | data = data.replace("-Wno-unused-private-field ", " ") 172 | 173 | with open(os.path.join(builddir, target, tflite_micro_project_folder, "Makefile"), 'w') as modified: 174 | modified.write("CCFLAGS = " + c_flags + "\n") 175 | modified.write("CXXFLAGS = " + cxx_flags + "\n") 176 | modified.write(data) 177 | 178 | shutil.copy(os.path.join(__folder__, "libtf.cc"), os.path.join(builddir, target, tflite_micro_project_folder)) 179 | shutil.copy(os.path.join(__folder__, "libtf.h"), os.path.join(builddir, target, tflite_micro_project_folder)) 180 | 181 | if os.system("cd " + os.path.join(builddir, target, tflite_micro_project_folder) + 182 | " && make -j " + str(cpus) + " lib"): 183 | sys.exit("Make Failed...") 184 | 185 | if os.path.exists((os.path.join(libdir, target))): 186 | shutil.rmtree(os.path.join(libdir, target), ignore_errors = True) 187 | 188 | os.mkdir(os.path.join(libdir, target)) 189 | 190 | shutil.copy(os.path.join(builddir, target, tflite_micro_project_folder, "libtensorflow-microlite.a"), os.path.join(libdir, target, "libtf.a")) 191 | convert_model(os.path.join(builddir, target, tflite_micro_project_folder, TF_LITE_MICRO, MODEL_DATA), os.path.join(libdir, "models/" + MODEL_NAME + ".tflite")) 192 | 193 | def build_target(target, __folder__, args, cpus, builddir, libdir): 194 | 195 | FLAGS = [ 196 | "-Wno-double-promotion", 197 | "-Wno-nonnull", 198 | "-Wno-psabi", 199 | "-Wno-sign-compare", 200 | "-Wno-unused-but-set-variable", 201 | "-Wno-unused-value", 202 | "-DGEMMLOWP_ALLOW_SLOW_SCALAR_FALLBACK", 203 | "-DNDEBUG", 204 | "-MMD", 205 | "-O3", 206 | "-fshort-enums", 207 | "-fno-delete-null-pointer-checks", 208 | "-fno-exceptions", 209 | "-mabi=aapcs-linux", 210 | "-nostartfiles", 211 | "-nostdlib", 212 | "-I" + os.path.join(__folder__), 213 | "-I" + os.path.join(__folder__, "edge-impulse-sdk"), 214 | "-I./" + os.path.join(TF_TOOLS_DOWNLOADS_PATH, "cmsis"), 215 | "-I./" + os.path.join(TF_TOOLS_DOWNLOADS_PATH, "cmsis/CMSIS/Core/Include"), 216 | "-I./" + os.path.join(TF_TOOLS_DOWNLOADS_PATH, "cmsis/CMSIS/DSP/Include"), 217 | "-I./" + os.path.join(TF_TOOLS_DOWNLOADS_PATH, "cmsis/CMSIS/NN/Include"), 218 | "-I./" + os.path.join(TF_TOOLS_DOWNLOADS_PATH, "kissfft") 219 | ] 220 | 221 | compile_flags = " ".join(FLAGS) 222 | c_compile_flags = compile_flags 223 | cxx_compile_flags = compile_flags + " -fno-use-cxa-atexit" 224 | 225 | if target == "cortex-m0plus": 226 | 227 | cortex_m0_plus_compile_flags = " -DARM_MATH_CM0PLUS" \ 228 | " -mcpu=cortex-m0plus" \ 229 | " -mfloat-abi=soft" \ 230 | " -mtune=cortex-m0plus" 231 | 232 | cortex_m0_plus_c_compile_flags = c_compile_flags + cortex_m0_plus_compile_flags 233 | cortex_m0_plus_cxx_compile_flags = cxx_compile_flags + cortex_m0_plus_compile_flags 234 | generate(target, "cortex-m0plus", __folder__, args, cpus, builddir, libdir, 235 | cortex_m0_plus_c_compile_flags, cortex_m0_plus_cxx_compile_flags) 236 | 237 | elif target == "cortex-m4": 238 | 239 | cortex_m4_compile_flags = " -DARM_MATH_CM4" \ 240 | " -mfpu=fpv4-sp-d16" \ 241 | " -mcpu=cortex-m4" \ 242 | " -mfloat-abi=hard" \ 243 | " -mtune=cortex-m4" 244 | 245 | cortex_m4_c_compile_flags = c_compile_flags + cortex_m4_compile_flags 246 | cortex_m4_cxx_compile_flags = cxx_compile_flags + cortex_m4_compile_flags 247 | generate(target, "cortex-m4+fp", __folder__, args, cpus, builddir, libdir, 248 | cortex_m4_c_compile_flags, cortex_m4_cxx_compile_flags) 249 | 250 | elif target == "cortex-m7": 251 | 252 | cortex_m7_compile_flags = " -DARM_MATH_CM7" \ 253 | " -mfpu=fpv5-sp-d16" \ 254 | " -mcpu=cortex-m7" \ 255 | " -mfloat-abi=hard" \ 256 | " -mtune=cortex-m7" 257 | 258 | cortex_m7_c_compile_flags = c_compile_flags + cortex_m7_compile_flags 259 | cortex_m7_cxx_compile_flags = cxx_compile_flags + cortex_m7_compile_flags 260 | generate(target, "cortex-m7+fp", __folder__, args, cpus, builddir, libdir, 261 | cortex_m7_c_compile_flags, cortex_m7_cxx_compile_flags) 262 | 263 | elif target == "cortex-m55": 264 | 265 | cortex_m55_compile_flags = " -DARM_MATH_CM55" \ 266 | " -mfpu=fpv5-d16" \ 267 | " -mcpu=cortex-m55" \ 268 | " -mfloat-abi=hard" \ 269 | " -mtune=cortex-m55" 270 | 271 | cortex_m55_c_compile_flags = c_compile_flags + cortex_m55_compile_flags 272 | cortex_m55_cxx_compile_flags = cxx_compile_flags + cortex_m55_compile_flags 273 | generate(target, "cortex-m55", __folder__, args, cpus, builddir, libdir, 274 | cortex_m55_c_compile_flags, cortex_m55_cxx_compile_flags) 275 | 276 | else: 277 | sys.exit("Unknown target!") 278 | 279 | def make(): 280 | 281 | __folder__ = os.path.dirname(os.path.abspath(__file__)) 282 | 283 | parser = argparse.ArgumentParser(description = 284 | "Make Script") 285 | 286 | parser.add_argument("--clean", "-c", action="store_true", default=False, 287 | help="Clean TensorFlow library.") 288 | 289 | parser.add_argument("--skip_generation", "-s", action="store_true", default=False, 290 | help="Skip TensorFlow library generation.") 291 | 292 | args = parser.parse_args() 293 | 294 | ########################################################################### 295 | 296 | cpus = multiprocessing.cpu_count() 297 | 298 | builddir = os.path.join(__folder__, "build") 299 | 300 | if not os.path.exists(builddir): 301 | os.mkdir(builddir) 302 | 303 | libdir = os.path.join(__folder__, "libtf") 304 | 305 | if not os.path.exists(libdir): 306 | os.mkdir(libdir) 307 | 308 | ########################################################################### 309 | 310 | if args.clean: 311 | if os.system("cd " + TF_TOP + 312 | " && make -f " + TF_TOOLS_MAKEFILE_PATH + " clean" + 313 | " && make -f " + TF_TOOLS_MAKEFILE_PATH + " clean_downloads"): 314 | sys.exit("Make Failed...") 315 | return 316 | 317 | if os.system("cd " + TF_TOP + 318 | " && make -f " + TF_TOOLS_MAKEFILE_PATH + " third_party_downloads"): 319 | sys.exit("Make Failed...") 320 | 321 | if os.path.exists((os.path.join(libdir))): 322 | shutil.rmtree(os.path.join(libdir), ignore_errors = True) 323 | 324 | os.mkdir(os.path.join(libdir)) 325 | 326 | if os.path.exists(os.path.join(libdir, "models")): 327 | shutil.rmtree(os.path.join(libdir, "models"), ignore_errors = True) 328 | 329 | os.mkdir(os.path.join(libdir, "models")) 330 | 331 | with open(os.path.join(libdir, "models/" + MODEL_NAME + ".txt"), "w") as f: 332 | f.write(MODEL_LABELS) 333 | 334 | shutil.copy(os.path.join(__folder__, "libtf.h"), os.path.join(libdir)) 335 | shutil.copy(os.path.join(__folder__, TF_TOP, "LICENSE"), os.path.join(libdir)) 336 | 337 | with open(os.path.join(libdir, "README"), "w") as f: 338 | f.write("You must link this library to your application with arm-none-eabi-gcc and have implemented putchar().\n") 339 | 340 | build_target("cortex-m0plus", __folder__, args, cpus, builddir, libdir) 341 | build_target("cortex-m4", __folder__, args, cpus, builddir, libdir) 342 | build_target("cortex-m7", __folder__, args, cpus, builddir, libdir) 343 | build_target("cortex-m55", __folder__, args, cpus, builddir, libdir) 344 | 345 | print("==============================\n Done\n==============================") 346 | 347 | if __name__ == "__main__": 348 | make() 349 | --------------------------------------------------------------------------------