add JavaScript Interpreter

This commit is contained in:
geniusgogo
2014-02-25 01:47:49 +08:00
parent 7255137b0a
commit 121bb5fcdf
115 changed files with 29947 additions and 13 deletions

View File

@@ -0,0 +1,46 @@
Contributing
===========
Thanks for thinking about contributing to Espruino! Anything you can add is hugely appreciated, but please can you follow a few simple rules:
* Keep the same coding style (See **Coding Style** below)
* Ensure that you are not contributing someone else's code, and that you are willing to add your code under Espruino's MPL Licence
* Make sure that what you do doesn't break the Espruino board or the other boards we build for. We can't check all the boards for every commit, so if you break something you'll annoy a whole bunch of people.
* Be aware that Espruino is designed for Microcontrollers - with very low amounts of flash and memory. Both are at a premium so don't statically allocate variables or do other stuff that will use up memory.
* Avoid randomly adding newlines, spaces, refactoring everything or renaming things to your own personal style (some things really could do with renaming, but please check first or we may reject your pull request)
* Don't add a whole bunch of indirection/abstraction for the sake of it - it'll probably just use of more of our precious memory.
* If you add a new API, try and make it familiar to Arduino/JavaScript users.
Target Areas
-----------
We'll keep the outstanding issues in GitHub's issue list, but general stuff that would really help us is:
* Tests. If something doesn't work, please make a test for it. Even if you don't fix it it'll help others greatly. Bonus points if it's in a pull request :)
* Documentation. Improving the documentation (either the EspruinoDocs project, or the auto-generated reference) would be fantastic.
* Duplication. If the same code is used for multiple platforms, try and make sure it's shared, not duplicated.
* Remove hard-coded stuff. Various things like the SPI filesystem are still hard-coded with ifdefs for each board - we want all that stuff to be generated from build_platform_info.py
* Speed. There are a few areas this could be improved - but please benchmark what you're doing both before and afterwards on the Espruino board to check that what you've done helps
* Memory Usage. Both RAM and Flash are at a premium. Ways of reducing this (including stack usage) and making usage more efficient are really appreciated.
* JavaScript compliance (without affecting speed or memory usage too much).
Contributing
-----------
* Please RUN THE TESTS to check that there are no regressions
* Issue us a pull request to [www.github.com/espruino] via GitHub
* Please keep each request small (just include one fix per request)
Coding Style
-----------
The rough coding style is as follows, but you should get a good idea from the code. If we've missed anything obvious please let us know!
* 2 Spaces for indents
* Open curly braces on the same line
* No Tabs used
* Use bool for booleans - not int
* ```//``` comments for single lines, ```/* ... */``` for multiple lines
* Half-hearted Doxygen compatibility: use ```///<``` for function declaration documentation (if on same line), and ```/** ... */``` if doing it right before a function
* Use new lines sparingly (only where it really makes sense)

515
components/external/espruino/ChangeLog vendored Normal file
View File

@@ -0,0 +1,515 @@
1v46 : ...
1v45 : Fix parseFloat("foo") not returning NaN (and assert) - fix #149
Remove Integer.parseInt
Fix parseInt("bar") - fix #150
Ensure that maths ops with null do treat it as 0 rather than a string - fix #156
Fix digitalPulse length (properly!) - fix #154
Making sure that undefined gets cast to NaN
Fix Array.indexOf() returns undefined instead of -1 - fix #155
Moved memory() to process.memory() - added more info too
Try and improve handling of PWM timer speeds
Fixed varying SPI baud rates depending on device
Makefile changes for OSX compile
1v44 : Modified build system to store binary names in the python definition
Fix nasty regression involving losing code at the end of Strings
Fix segfault when pinMode is called on an invalid pin
Now disable interrupts during 4 bit SPI send - it's just too much otherwise
Detect unfinished block comments in console (fix #138)
Fix flash write on most 10XxB boards
Fix PWM output on all STM32 boards
General hardware tidy in prep for more intelligent device management
Run initialisation code before setWatch, to make sure pullup/down is set beforehand
Change 'Pin' datatype to be an unsigned char - makes tests easier
Now use the hardware RTC for keeping system time. Allows proper deep sleep on Espruino board
FINALLY - fix the USB VCP lost characters issue (#94)
1v43 : Added 'Modules' object with support for adding/removing cached modules
Allow product ID to be changed via Makefile
Fix documentation (and old-fashined Parsing style) for JSON
build_jswrapper now outputs errors to stderr (more compatible with default (silent) build process)
Fix issue when parsing quotes in strings
Added void operator for closure minification compatibility
Ensure that return takes the comma operator
Fix issue where printing Infinity would crash Espruino (fix #129)
Finally some working (extremely beta) cc3000 code
Added jsvObjectGet/SetChild to simplify some wrappers
'http' now uses JsVars for storage (so is suitable for non-linux devices)
Turned 'http' into a library
Added process.version and process.env (fix #131)
Changed handling of 2nd arg of << so that precedence is correct
Fixed handling of 'for (;;)'
Fix lock leak in Module handling
Update ST's library for the STM32F1
Update ST's VCP implementation
Added prefix operator (fix #130)
Allow espruino for linux to be run with '#!' in scripts
Fix indexOf on final element of strings (fix #133)
Remove JSV_PARENTINFO, as it turns out JS doesn't keep track of function scopes anyway (fix #109)
Make 'this' a keyword (now faster, more memory efficient)
Make 'Hardware' (root) the default value of 'this'
Add jsvArrayPushAndUnLock and modified code to use it (fix #135)
Now remember I2C state (partial fix for #13)
Replace 'pow' function with a smaller version - save ~2kb
Shaved another 1200 bytes off jslTokenAsString
Now store Pin state (fix for #13 on F1 parts, F4 still looks broken)
Added Graphics.stringWidth
Added internal Printf function
Misc speed and code size improvements
This version has gone to Seeed for use on the KickStarter boards
1v42 : [ebirger] allowing 'new' with no brackets
Allow built-in functions with variable numbers of arguments (fix #83)
Implement 'String' constructor in the normal way (fix #110)
Fix regression with parsing constructors while not executing
Allow multiple arguments to print and console.log (fix #92)
Make 'arguments' array available in functions (fix #100)
Fix an assert fail, and handle some potential memory leaks
Don't show __proto__ and constructor with for..in, keys(), or JSON.stringify
Make 'trace()' output more readable debug data for complex structures
Fix memory leak whe parsing functions iwht variable numbers of arguments - fix #115
Defined NaN
Stop 'new undefined()' crashing Espruino - fix #120
Get A13/A14 working on Espruino board (these were JTAG)
Get bootloader size direct from Python (remove hard-coding)
Fix '~' operator when acting on variables
Made bootloader a bit more error tolerate (CRC on write)
Added %=, /=, and *= operators (fix #121)
Allowed Object.toString() to take a radix argument for integers (fix #125)
Fix error message issue - broken strncat (fix #124)
Add comma operator (fix #122)
Added some basic code for STM32F429IDISCOVERY - not currently working though
This version is the one sent off on the Test Harness (so will probably appear on boards)
1v41 : Fix Olimexino compile (https://github.com/espruino/Espruino/issues/6)
[ebirger] Member constructors (eg. new a.b() )
[ebirger] Ensuring integers with radix specifiers can still be parsed if a radix is specified
Fix for tests/test_json_arraybuffer_001.js - iteration of arraybuffers of length==1
Add Object.keys(...)
More arraybuffer iteration fixes
On linux, use built-in stringToFloat to aid debugging. Handle exponentials, fix #31
'make serialflash' is now works correctly for Espruino Boards with bootloader
setWatch(..A0);setWatch(..A0);clearWatch(1) does not now kill the other watch, fix #25
One-based setTimeout/setWatch, fix #3
Added Function.call and Function.apply, fix #54
'http' and 'fs' are now libraries that need to be 'require'd, fix #8
Updated pin info for STM32F103xC/D/E chips, fix #84
Fixed linker script for STM32F4 (discovery board now works)
Object prototypes are now Objects, fix #101
Board docs now specify '3.3v' only pins fix #104
Add Array.forEach
Fix searching down >1 prototype to find functions (one more issue posted in #99)
Fix "12345"/5 type issues (fix #90)
'Consting' some string functions
Fixing arrays with string indices that are actually numbers \o/ (fix #19)
Released onto website
1v40 : Ensure that LCD.prototype.setPixel = function actually works
Refactor LCD driver code to allow lcdInit (and start of making it non-platform-specific)
Built 'LCD' support into linux/raspi/carambola
Add initial SPI.send(ArrayBuffer) support - even if NO VALUES RETURNED
Start of built-in Nokia 5110 LCD support
Remove GPIO clock removal on sleep for now (it kills setWatch)
Fix (sub)ArrayBuffer problems (test100.js)
Added setDeepSleep - still beta put power consumption drops to 1mA
Fix broken name for httpCRq.write
Changed LCD to Graphics - added ability to render to ArrayBuffer
Fix 8 char built-in class names
Adding preliminary Sony SmartWatch support
Adding preliminary support for completely bare 36 pin chip
Fixing pin defs for Espruino board rev 1v1
Added proper SDL/ArrayBuffer and JS Callback graphics support
Added "ifdef" ability in build_jswrapper
Take JSVAR_CACHE_SIZE out of jsutils and put it in the board config file
Added JSV_PARENTINFO which will allow us to do things like setTimeout(foo.bar,10)
Fixed arrays in non-executes streams - 'if (0) print([1,2,3]);'
Added 'require' function loading modules from node_modules on SD card
Added module cache to stop modules being re-loaded
Renamed internal vars to start with '>' - much easier to distinguish for 'dump'/etc
Only use parentInfo on functions
Load all tests in test dir - don't do them by number
Added 'zigzag' ordering for ArrayBuffer Graphics
Added 'vertical_byte' ordering for ArrayBuffer Graphics
toJSON now ignores 'hidden' object elements
Special-case jsvArrayBufferIteratorSetIntegerValue
Make SPI output an ArrayBuffer
Use best out of 3 for DelayMicroseconds calibration - something seems flaky right after bootup
Lines now drawn from p1 to p2 inclusive
Events now use jshPushIOWatchEvent (should cut down on code) also fixed bug with watching pin #11
Now remember if pinMode was set or not
Transform ```code``` in JSON into a code tag in the documentation
Graphics now supports FSMC for HY boards again
Drawing vector fonts is now roughly the right size and position (still not 100%)
Remove registration code
Adding MPL licence
Remove Arduino bit manipulation functions - nobody seems to use them anyway
# of flash pages/etc now comes from board info
[ebirger] Supply the correct arguments to Array.map
[ebirger] Method calls and membership evaluation should be done on all factors (ee. [1,2,3].foo())
[ebirger] When running multiple tests, only set up terminal once or it breaks the terminal window on exit
Added STM32-style USB CDC bootloader for Espruino Boards
Added scripts/create_espruino_image.sh to package up bootloader and espruino into one binary
SHIPPED on Impatient developer boards
1v39 : Added Bitwise NOT operator
Added Raspberry Pi version to ZIP (with HTTP support)
Fixed load/save on Linux Devices
Added pinMode function (to allow pull-ups/pull-downs to be turned on)
SPI.send4bit/send8bit will now not mess up the final element
changeInterval now clears up stored up callbacks (eg, setInterval(.., 0.01)...wait...changeInterval(...,20)
Ctrl-C no longer prints anything, which avoids lockups
No longer print "Execution Interrupted" if nothing was interrupted!
Added >>>= >>= and <<=
When entering text interactively, ensure that there are no trailing spaces
1v38 : Tweaks for Arduino IDE compile
Removed '(char #)' from stack trace, as a bit pointless now
Added better reporting of execution location when Ctrl-C pressed
Urgent fix for non-working Olimexino since 1v33
Fix string comparison when strings contain "\0"
Added LED1/2/OSC/SD/etc to Olimexino Board docs
1v37 : Urgent fix - power saving code made it difficult to re-flash Espruino (now only apply this to Espruino Board)
1v36 : Fix documentation for Array.pop()
Added some much better board documentation
Fixed DAC output on F3
Fixed DAC output on devices where PWM is also available and the alternate function is less than the DAC's
1v35 : Attempt to reduce power consumption when sleeping by turning off GPIO, and setting GPIOs to AIN on reset
Fix F3 issue where ADC/DAC weren't picked up properly
Tidy up register text and add KickStarter mention
var a = {}; a[LED1]=0; - not converted to String
JSON (and hence dump()) now dumps ArrayBuffer correctly
1v34 : Faster jshFromDeviceString
Preliminary support for flow control on Serial receive
Speed improvements by removing jsvGetRef from jsvUnLock
fast 4 byte pre-check in jsvFindChildFromString
Skip lock/unlock in FindChildFromString to help increase speed
When we unplug USB, only go to the default console device IF that is the device we're currently on
Support for custom Espruino board
Added ArrayBufferView.interpolate
16 bit SPI send for send4bit/sevrnd8bit (better reliability on low-end chips)
Fix JSON dump of typed array
Added Math.clip(x, min, max)
When saving on flash, don't do jslTokenAsString properly
B3/B4 move from alternate fn
Fix incorrect reporting of analog pins
Fix I2C.readFrom on STM32F1/4
Make 1/2 == 0.5 (was being sensible before, but now follow JS spec)
Ctrl-C while in timer fn clears timers (but not outside it)
Fixed broken clearInterval from within setInterval
Hopefully fixed issue on SSD1289 LCD controller
Trigger wheel handler to use interrupts
2D arraybuffer interpolation
Added Math.wrap, fixed a lot of trigger issues
Fixed SysTick priority/preempt problems
Slowed the SysTick timer back down for everything
Fix Int8Array signedness on F4 boards
Refactored source code tree
1v33 : fix character encoding issue of "\16"+"1" != "\161"
Refactoring of ArrayBuffer into iterator, and addition of a general purpose iterator
Fancier assert for debugging
jsvArrayJoin to use new iterator
for (i in ...) to use new iterator
I2C and SPI use new iterator
Serial.write() - to allow single ints to easily be written
changeInterval assert fail when given a function by accident
added peek8/poke8/peek16/poke16
memory() now takes account of command history size
memory() on ARM reports the end address of the stack - so it can be used as a scratchpad with peek and poke
Try and reduce code size by not inlining several functions
No refs for StringExts - so we get one more byte per JsVar (~5%) more storage efficiency
Move from jsvIsBuiltInFunction to computer-generated jswIsBuiltInFunction
When creating Objects, check for built-in function BEFORE creating an Object class for it
Built process now checks that flash usage is under the allowed value
Added short compare to jswHandleFunctionCall to reduce code size
Added 3 byte compare (4 byte read and AND off top byte) - faster, less code
Auto-generate jsvGetBasicObjectName from docs
No longer using refs for storing whether free or not - use flags with JSV_UNUSED and get one extra var with 8 bit refs
Switch to using STRING_0...STRING_MAX in flags, rather than specific bits in JsVarFlags - allows more that 15 chars to be used per JsVar
Make ArrayBuffers actually be ArrayBufferViews - saves on extra string-handling code at expense of one var
Make sure Uint8Array,etc inherits from ArrayBufferView
Fix issue where a '\0' coming in from serial was not put in e.data properly
Don't inline some functions when we're trying to save on flash
Re-use sin for cos, pow for sqrt to reduce code size
1v32 : Fixed embarassing issue with 0.999=="0.A"
Added and checked Pin.writeAtTime on STM32
Now don't allocate events array - just allocate directly, which saves memory and is faster (although slighty out of order)
Docs: now Alphabetically sorted, and class instances not listed by accident
Fix issue where Ctrl-C on ANY Serial port caused execution to be interrupted
Updated busy indicator to cope with recent change to not allocate events in an array
Fixed I2C on HY 2.4 board - I2C needed hard reset
Added basic ArrayBuffers/TypedArray support
Fix memory leak when error created with [] on a non-array/object
Improved hyperlinking in documentation
Fix I2C receive bug on F4
Increased VL board's input buffer size
1v31 : Fix PWM output on TIMER1/8 pins of the STM32F4
Fix PWM output for negated timers
memory() now runs a GC pass
Fixed multiple occurrence of functions in reference
1v30 : STM32F1: fixed AF issue meant peripherals would never return from AF mode
STM32F1: When given an invalid pin, now reports if pins are 'af' or not
Updated SPI.setup docs to mention that you can't mix AF and non-AF
If one SPI pin is specified but others aren't, only that pin will be set up
Added Olimexino hack so SPI1.setup works as expected
Allow using [] on a function
Fix precedence issue, so var a = function() { return 1; }(); works
Update SPI documentation
for (i in f) can now iterate over functions
Optional argument to trace() for object to start tracing from
Small steps towards ArrayBuffers
Added smart edit that checks for internal functions, and uses Function.replaceWith
Added Function.replaceWith to replace the internals of a function while keeping the scope
1v29 : Some hacky sysfs-based IO for running on Linux
HTTP Callbacks are now stored as names so they can be changed on the fly (Linux only)
Successful compile for Carambola
Filesystem support on Linux
Switch to variable size ref counter (marginally more efficient on very small devices, safe on Linux)
Linux now has unlimited memory available
Added linux/sysfs 'setWatch' (non-irq driven, so very noddy)
Checked jswrapper check from using multi-char constants to a #define
Improve pin suggestions for SPI/I2C/USART
Auto-initialise USART with default values when setConsole is used
Support for new Graphics LCD types
3.2" VCT6 board support
1v28 : Faster LCD fillrect for HY 2.8
Fix for multi-byte SPI writes on HY board at 1Mhz (touchscreen control bug)
Fix issue with delayMicrosecond calibration on HY (and hence OneWire)
Fixed digitalPulse on STM32VLDISCOVERY
1v27 : Fixed problem with OneWire constructor execution
Added |=, &= and ^=
Added Array.splice()
Faster, more ROM-efficient built-in symbol table
Fix for potential issue when using field accessor on an undefined var
1v26 : I2C Support on STM32F1 and STM32F4 boards too
Emergency cut in variables for Olimexino with bootloader (as flash usage has got too high for save to flash!)
1v25 : http.writeHead to accept an empty header
Fixed issue finding methods on built in classes (0 termination)
make sure http server with no data still sends headers...
Start of MINI-HY-2.8" support (all ok, but no SD card yet)
Reduce RAM usage by consting some arrays that are not modified
Vector fonts now use polys - 8kb less ROM, and faster rendering
Start of LCD 'driver' code
Standard way of handling events, Object.on/emit/removeAllListeners - like Node.js's EventEmitter
Self-calibrating Microsecond delay (for intermal OneWire/etc)
OneWire class
Correct handling of built-in class constructors
Fix error when parsing a zero-argument function that has been given arguments
I2C support - currently ONLY tested on STM32F3 board
1v24 : SDIO-based fat driver on the HY STM32 board
Added DAC to the HY boards (103xE-based)
Re-named the fileSystem functions to make them more compatible with node.js (readFile/writeFile/etc)
Added fs.appendFile
Removed HTTP from the reference until it is included in some boards
1v23 : Fix 'ERROR: INTERNAL: stmADCChannel' on STM32VLDISCOVERY/F1 boards when accessing PA0
Reference now mentions which Espruino version it is for
1v22 : Important fix - Events got executed in the wrong order if they got queued up
1v21 : Ensure SPI clock does not stop between bytes
Added SPI.send4bit and SPI.send8bit
Made sure the VL board's code fits into available flash
Smart += that can append to a string rather than cloning it
dump() prints functions properly, rather than 'var f = function() {}'
Pageup/down move the cursor to the beginning/end of input
LCD draw/fill with negative x and y
1v20 : Add console.log
Fix automatic usleep for Linux
Added node.js-style HTTP server for Linux version
Fixed null-pointer issue when accessing something that doesn't exist on an object
Added node.js-style HTTP client for Linux version
Start of bit bashing functionality
for (i in "ABCD") console.log(i) -> 0,1,2,3
String array access (but not for writing - doesn't work in JS anyway)
String String.fromCharCode / charCodeAt
Added SPI baud rate setting
Vector font chars 'a' and '4' now work ok
Fix numeric exception when rendering a poly that has some identical points
Better digitalPulse (uses timer + interrupts)
analogWrite can now take an object with a 'frequency' argument for PWM
1v19 : Fixed issue where var M=Math;M.random() failed
Fixed issue with var U=USB;U.print("Hello");
Remove loop iteration limit
Fix memory leak when a syntax error is in for '(i in arr)'
Save state of pin on setWatch interrupt (e.state)
Change setWatch to allow only on rise or fall as an option
clearWatch() clears all watches
1v18 : DAC support on F3/F4
Serial.setup() can also take a second parameter of an object {tx,rx}
Better support for dump() with echo/setBusyIndicator/etc
Better dumping of prototypes on built-in vars
Don't add chars<32 (Except tab) to the input line
SPI1/2/3/4.setup() to take an object {baud,sck,miso,mosi}
Better hardware initialisation code (not UARTS auto-init if they are used)
Fix issues with prototypes
Peek/poke instructions
Start of I2C support (not usable yet)
Added Math. ceil/floor/exp/log
1v17 : Support for running alongside the Maple bootloader
Fix parsing of numbers beginning with 0 when forceRadix!=8
Fixed USART1 on Maple/Olimexino devices
1v16 : Inlining of jsvLock/UnLock in jsvar.h to improve speed
Move non-hardware-dependent stuff into jsdevices
Move jshardware.c into targets/stm32/jshardware.c, create 'targets/linux' and use a single makefile
For + While loops work without reallocating lex
Fix AddNativeFunction when function already exists (and tests + saved state)
Change jsvFindChildFromX to use JsVar* from JsVarRef - saves a lot of lock/unlock
Handle new Foo() as per spec (return value + init of this+prototype) - still does not cope with non-object prototype
Beginning of SD card support (works on Olimexino, but not very flexible)
Fix for parse/eval when given non-strings
Strings can now contain '\0'
Jumptable-friendly reserved word check
Jumptable-friendly builtin functions (massive refactor)
SPI support
HY board support, and graphics LCD
Added fillPoly, and Vector fonts
Added Registration code
Fixed some undefined function/array warnings
Much better HTML function documentation
Fixed edit() function
STM32F3 support, and now peripheral stuff is done with a script
explain what pins are available if a pin is not capable of requested fn
power on ADCs only when needed
LCD fillPoly speed improvements, + drawLine
Add datatype for Pin, so pins written to console by pin name rather than integer value.
Added Pin.set/Pin.reset
Change warning about 'undefined.' into an error (foo.reset() had unexpected consequences!)
Fix parsing of '1.0/-3'!
Add typeof and instanceof operators
Ensure that Serial1/SPI1/etc are objects of type 'Serial'/'SPI' - so prototypes can be added
1v15 : Escaping JSON strings
Fix parsing of octal numbers in strings (so don't have to be 3 chars long)
Drastically improved stack usage using small stub functions (at expense of a bit of speed)
dump() also dumps out prototypes for functions
1v14 : Fix complaint about pins during setBusyIndicator()
Increase available memory on OLIMEXINO
Added function memory() to return memory usage
setWatch now links to function names (rather than just functions)
dump() also handles Serial.onData(...)
Fix issue with JSON printing functions with arguments to console
prefix builtin variables with '_'
fix ArrayIndexOf when array contains undefineds
move all devices into one git repository
USB on F4
call onInit function/string if it exists when Espruino powers on
Compile F4 with -O2 - as we have the program memory for it
Serial3/4/5/6 on F4
Serial3 on Olimexino
Make Serial.onData() clear onData handler
1v13 : Operations like + on Object/Array convert them to strings rather than error
var now doesn't error if there is no semi-colon
Allow new line or line delete in multi-line editing
add edit(functionName) - which copies function definition into inputline so it can be updated
When printing lines, delete current inputline and then put it back in idle loop (only if echo=1)
Support *,/ etc on numpad
1v12 : Issue when printing lots of data and then disconnect USB
Hide USB/Serial in Dump()
add Array.map(fn(x), thisArg)
For newline, count [] and () (as well as {}) - also knows about comments/strings/etc
Fix assert fail is setTimeout with non-function
If space at end of input line, enter still executes
Removed some hard-coded arrays in favour of JsVar strings
Fix confusion with jsvIsName/jsvIsString
Handle numpad end key
Add code to check stack and stop stack overflow if too much recursion
Ensure that setTimeout/setWatch store the link to a function, not the function
Fix nasty ref loop in ref loop GC issue
Add dotty output
Fix memory leak when error in jspParseSingleFunction
Now run Garbage collection if we're idle, and we know we have a few ms spare
Added setSleepIndicator
Fix line/col indicator in errors/warnings
Fix JSON parsing and printing when 'undefined' encountered
Rewritten object handling code to be way more standard JavaScript compliant
Array initialisation with 'new Array()', also for Strings
Added a few more built in functions
Nice error reporting with line + pointer
fixed Math.random
Binary style ops on doubles now work - they are just converted to ints
Added boolean datatype
1v11 : Add Math functions
Add command history (and dynamic history free if low memory)
Fix broken jsvArrayPop
Add tests for and fix Array.indexOf
In-line editing for commands
Fix bug in basicVarEquals for big strings
More fixes for low memory conditions
Multi-line edit for commands (but no newline or line delete yet)
Handle Home, End + reverse delete keys
Fix nested for loops not handling interrupts correctly
Fix AppendString issue when given start value greater than string
Add 'changeInterval' to allow things created with setInterval to have the frequency changed (eg. stepper motor control)
Now puts itself to sleep to save power, when it knows nothing is required and it'll be woken up by SysTick before
Change Math library to avoid putting constants in RAM
1v10 : Increase FIFO size for VL
Marginally decrease amount of F4 vars to ensure they all fit in one flash sector
Allow strings to be longer than the max token size
'"key" in obj' syntax
Detect if in FOR or WHILE loop, and if not, disallow break and continue
Change min setInterval time to 0.1ms - F4 can get close to this
Better analog pin error message
USB support on Olimexino/Maple
Start of multiple COM port support (ioEvent queue)
Ctrl-C now clears the input line
Save state of 'echo' into flash with save()
Add 'setBusyIndicator(pin)' to set pin high when Espruino is busy
Inbuilt function handling speed improvements
Allow Serial comms via other UARTS. Serial1/2.onData and print/println
now inserts elements into arrays in the correct order (GetLength can be (is) now much faster)
Faster code to work out pins from strings
Automatically convert IDs in form A#,A##,B#,B## etc into numbers.
Built-in constants for LED1/BTN/etc.
1v09 : Enabled 'abs' by default
Added flash programming to STM32F4
analogWrite now working!
1v08 : Add preliminary STM32F4 support
Allowed test cases to test timers - eg. code in jsinteractive.c
Fix memory leak for timer
Fix memory leak for digitalWrite
1v07 : Fix string charAt
Fix watch on different pin
Pass arguments to event handlers - eg. time
digitalWrite/Read to take arrays of pins, and int for value
1v06 : Add break + continue
Add switch statement
Handle /r, /r/n or just /n for newlines - phone compatible
Handle different type of delete
1v05 : Allow setWatch/setTimeout/setInterval with a string
Handle adding Open bracket then deleting it
When calling a NAMED function, zero the scopes - this stops scope table overflow
1v04 : Renamed to Espruino
Fixed issue with event add when out of memory
If out of memory happens during a timer, kill all timers

378
components/external/espruino/LICENSE vendored Normal file
View File

@@ -0,0 +1,378 @@
All files in this package are Copyright 2013 Gordon Williams, Pur3 Ltd unless
otherwise noted.
-------------------------------------------------------------------------------
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.

969
components/external/espruino/Makefile vendored Normal file
View File

@@ -0,0 +1,969 @@
# This file is part of Espruino, a JavaScript interpreter for Microcontrollers
#
# Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# -----------------------------------------------------------------------------
# Makefile for Espruino
# -----------------------------------------------------------------------------
# Set ONE of the following environment variables to compile for that board:
#
# ESPRUINO_1V0=1 # Espruino board rev 1.0
# ESPRUINO_1V1=1 # Espruino board rev 1.1 and 1.2
# ESPRUINO_1V3=1 # Espruino board rev 1.3
# OLIMEXINO_STM32=1 # Olimexino STM32
# OLIMEXINO_STM32_BOOTLOADER=1 # Olimexino STM32 with bootloader
# EMBEDDED_PI=1 # COOCOX STM32 Embedded Pi boards
# HYSTM32_24=1 # HY STM32 2.4 Ebay boards
# HYSTM32_28=1 # HY STM32 2.8 Ebay boards
# HYSTM32_32=1 # HY STM32 3.2 VCT6 Ebay boards
# STM32VLDISCOVERY=1
# STM32F3DISCOVERY=1
# STM32F4DISCOVERY=1
# STM32F429IDISCOVERY=1
# CARAMBOLA=1
# RASPBERRYPI=1
# LPC1768=1 # beta
# LCTECH_STM32F103RBT6=1 # LC Technology STM32F103RBT6 Ebay boards
# Or nothing for standard linux compile
#
# Also:
#
# DEBUG=1 # add debug symbols (-g)
# RELEASE=1 # Force release-style compile (no asserts, etc)
# SINGLETHREAD=1 # Compile single-threaded to make compilation errors easier to find
# BOOTLOADER=1 # make the bootloader (not Espruino)
# PROFILE=1 # Compile with gprof profiling info
ifndef SINGLETHREAD
MAKEFLAGS=-j5 # multicore
endif
INCLUDE=-I$(ROOT) -I$(ROOT)/targets -I$(ROOT)/src -I$(ROOT)/gen
LIBS=
DEFINES=
CFLAGS=-Wall -Wextra -Wconversion -Werror=implicit-function-declaration -fdiagnostics-show-option
OPTIMIZEFLAGS=
#-fdiagnostics-show-option - shows which flags can be used with -Werror
# Espruino flags...
USE_MATH=1
ifeq ($(shell uname -m),armv6l)
RASPBERRYPI=1 # just a guess
endif
ifeq ($(shell uname),Darwin)
MACOSX=1
endif
# Gordon's car ECU (extremely beta!)
ifdef ECU
STM32F4DISCOVERY=1
#HYSTM32_32=1
USE_TRIGGER=1
DEFINES += -DECU
endif
ifdef RELEASE
# force no asserts to be compiled in
DEFINES += -DNO_ASSERT
endif
CWD = $(shell pwd)
ROOT = $(CWD)
PRECOMPILED_OBJS=
PLATFORM_CONFIG_FILE=gen/platform_config.h
BASEADDRESS=0x08000000
###################################################
# When adding stuff here, also remember build_pininfo, platform_config.h, jshardware.c
ifdef ESPRUINO_1V0
USB=1
#USE_NET=1
#USE_CC3000=1
USE_GRAPHICS=1
USE_FILESYSTEM=1
FAMILY=STM32F1
CHIP=STM32F103RG
BOARD=ESPRUINOBOARD_R1_0
DEFINES+=-DESPRUINOBOARD
STLIB=STM32F10X_XL
PRECOMPILED_OBJS+=$(ROOT)/targetlibs/stm32f1/lib/startup_stm32f10x_hd.o
OPTIMIZEFLAGS+=-O3
else ifdef ESPRUINO_1V1
DEFINES+=-DESPRUINO_1V1
USE_BOOTLOADER=1
BOOTLOADER_PROJ_NAME=bootloader_espruino_1v1
USB=1
USE_NET=1
USE_CC3000=1
USE_GRAPHICS=1
USE_FILESYSTEM=1
FAMILY=STM32F1
CHIP=STM32F103RC
BOARD=ESPRUINOBOARD_R1_1
DEFINES+=-DESPRUINOBOARD
STLIB=STM32F10X_XL
PRECOMPILED_OBJS+=$(ROOT)/targetlibs/stm32f1/lib/startup_stm32f10x_hd.o
OPTIMIZEFLAGS+=-Os # not that short on memory, but Travis compiler is old and uses more
else ifdef ESPRUINO_1V3
DEFINES+=-DESPRUINO_1V3
USE_BOOTLOADER=1
BOOTLOADER_PROJ_NAME=bootloader_espruino_1v3
USB=1
USE_NET=1
USE_CC3000=1
USE_GRAPHICS=1
USE_FILESYSTEM=1
FAMILY=STM32F1
CHIP=STM32F103RC
BOARD=ESPRUINOBOARD
STLIB=STM32F10X_XL
PRECOMPILED_OBJS+=$(ROOT)/targetlibs/stm32f1/lib/startup_stm32f10x_hd.o
OPTIMIZEFLAGS+=-O3
else ifdef OLIMEXINO_STM32
USB=1
USE_FILESYSTEM=1
FAMILY=STM32F1
CHIP=STM32F103RB
BOARD=OLIMEXINO_STM32
STLIB=STM32F10X_MD
PRECOMPILED_OBJS+=$(ROOT)/targetlibs/stm32f1/lib/startup_stm32f10x_md.o
OPTIMIZEFLAGS+=-Os # short on program memory
else ifdef OLIMEXINO_STM32_BOOTLOADER
USB=1
USE_FILESYSTEM=1
FAMILY=STM32F1
CHIP=STM32F103RB_MAPLE
DEFINES += -DSTM32F103RB
SAVE_ON_FLASH=1
BOARD=OLIMEXINO_STM32_BOOTLOADER
STLIB=STM32F10X_MD
PRECOMPILED_OBJS+=$(ROOT)/targetlibs/stm32f1/lib/startup_stm32f10x_md.o
OPTIMIZEFLAGS+=-Os # short on program memory
else ifdef EMBEDDED_PI
USB=1
# USE_FILESYSTEM=1 # no SD-CARD READER
FAMILY=STM32F1
CHIP=STM32F103RB
BOARD=EMBEDDED_PI
STLIB=STM32F10X_MD
PRECOMPILED_OBJS+=$(ROOT)/targetlibs/stm32f1/lib/startup_stm32f10x_md.o
OPTIMIZEFLAGS+=-Os # short on program memory
else ifdef HYSTM32_24
USB=1
USE_GRAPHICS=1
USE_LCD_FSMC=1
USE_FILESYSTEM=1
USE_FILESYSTEM_SDIO=1
FAMILY=STM32F1
CHIP=STM32F103VE
BOARD=HYSTM32_24
STLIB=STM32F10X_HD
PRECOMPILED_OBJS+=$(ROOT)/targetlibs/stm32f1/lib/startup_stm32f10x_hd.o
OPTIMIZEFLAGS+=-O3
else ifdef HYSTM32_28
USB=1
USE_GRAPHICS=1
USE_LCD_FSMC=1
DEFINES+=-DILI9325_BITBANG # bit-bang the LCD driver
SAVE_ON_FLASH=1
#USE_FILESYSTEM=1 # just normal SPI
FAMILY=STM32F1
CHIP=STM32F103RB
BOARD=HYSTM32_28
STLIB=STM32F10X_MD
PRECOMPILED_OBJS+=$(ROOT)/targetlibs/stm32f1/lib/startup_stm32f10x_md.o
OPTIMIZEFLAGS+=-Os
else ifdef HYSTM32_32
USB=1
USE_GRAPHICS=1
USE_LCD_FSMC=1
USE_FILESYSTEM=1
USE_FILESYSTEM_SDIO=1
FAMILY=STM32F1
CHIP=STM32F103VC
BOARD=HYSTM32_32
STLIB=STM32F10X_HD
PRECOMPILED_OBJS+=$(ROOT)/targetlibs/stm32f1/lib/startup_stm32f10x_hd.o
OPTIMIZEFLAGS+=-O3
else ifdef STM32F4DISCOVERY
USB=1
#USE_NET=1
#USE_CC3000=1
USE_GRAPHICS=1
DEFINES += -DUSE_USB_OTG_FS=1
FAMILY=STM32F4
CHIP=STM32F407
BOARD=STM32F4DISCOVERY
STLIB=STM32F4XX
PRECOMPILED_OBJS+=$(ROOT)/targetlibs/stm32f4/lib/startup_stm32f4xx.o
OPTIMIZEFLAGS+=-O3
else ifdef STM32F429IDISCOVERY
USB=1
USE_GRAPHICS=1
#USE_LCD_FSMC=1
DEFINES += -DUSE_USB_OTG_FS=1
FAMILY=STM32F4
CHIP=STM32F429
BOARD=STM32F429IDISCOVERY
STLIB=STM32F4XX
PRECOMPILED_OBJS+=$(ROOT)/targetlibs/stm32f4/lib/startup_stm32f4xx.o
OPTIMIZEFLAGS+=-O3
else ifdef SMARTWATCH
DEFINES+=-DHSE_VALUE=26000000UL
USB=1
FAMILY=STM32F2
CHIP=STM32F205RG
BOARD=SMARTWATCH
STLIB=STM32F2XX
PRECOMPILED_OBJS+=$(ROOT)/targetlibs/stm32f2/lib/startup_stm32f2xx.o
OPTIMIZEFLAGS+=-O3
else ifdef STM32F3DISCOVERY
#USE_BOOTLOADER=1
#BOOTLOADER_PROJ_NAME=bootloader_espruino_stm32f3discovery
USB=1
FAMILY=STM32F3
CHIP=STM32F303
BOARD=STM32F3DISCOVERY
STLIB=STM32F3XX
PRECOMPILED_OBJS+=$(ROOT)/targetlibs/stm32f3/lib/startup_stm32f30x.o
OPTIMIZEFLAGS+=-O3
else ifdef STM32VLDISCOVERY
FAMILY=STM32F1
CHIP=STM32F100RB
BOARD=STM32VLDISCOVERY
STLIB=STM32F10X_MD_VL
PRECOMPILED_OBJS+=$(ROOT)/targetlibs/stm32f1/lib/startup_stm32f10x_md_vl.o
OPTIMIZEFLAGS+=-Os # short on program memory
else ifdef TINYCHIP
FAMILY=STM32F1
CHIP=STM32F103TB
BOARD=TINYCHIP
STLIB=STM32F10X_MD
PRECOMPILED_OBJS+=$(ROOT)/targetlibs/stm32f1/lib/startup_stm32f10x_md.o
OPTIMIZEFLAGS+=-Os # short on program memory
else ifdef LPC1768
MBED=1
FAMILY=LPC1768
CHIP=LPC1768
BOARD=LPC1768
MBED_GCC_CS_DIR=$(ROOT)/targets/libmbed/LPC1768/GCC_CS
PRECOMPILED_OBJS+=$(MBED_GCC_CS_DIR)/sys.o $(MBED_GCC_CS_DIR)/cmsis_nvic.o $(MBED_GCC_CS_DIR)/system_LPC17xx.o $(MBED_GCC_CS_DIR)/core_cm3.o $(MBED_GCC_CS_DIR)/startup_LPC17xx.o
LIBS+=-L$(MBED_GCC_CS_DIR) -lmbed
OPTIMIZEFLAGS+=-O3
else ifdef CARAMBOLA
BOARD=CARAMBOLA
DEFINES += -DCARAMBOLA -DSYSFS_GPIO_DIR="\"/sys/class/gpio\""
LINUX=1
USE_FILESYSTEM=1
USB=1
USE_GRAPHICS=1
USE_NET=1
else ifdef RASPBERRYPI
BOARD=RASPBERRYPI
DEFINES += -DRASPBERRYPI -DSYSFS_GPIO_DIR="\"/sys/class/gpio\""
LINUX=1
USE_FILESYSTEM=1
USB=1
USE_GRAPHICS=1
#USE_LCD_SDL=1
USE_NET=1
else ifdef LCTECH_STM32F103RBT6
USB=1
SAVE_ON_FLASH=1
FAMILY=STM32F1
CHIP=STM32F103RB
BOARD=LCTECH_STM32F103RBT6
STLIB=STM32F10X_MD
PRECOMPILED_OBJS+=$(ROOT)/targetlibs/stm32f1/lib/startup_stm32f10x_md.o
OPTIMIZEFLAGS+=-Os
else
BOARD=LINUX
LINUX=1
USE_FILESYSTEM=1
USB=1
USE_GRAPHICS=1
#USE_LCD_SDL=1
ifndef MACOSX
# http libs need some tweaks before net can compile
USE_NET=1
endif
endif
PROJ_NAME=$(shell python scripts/get_binary_name.py $(BOARD) | sed -e "s/.bin$$//")
ifeq ($(PROJ_NAME),)
$(error Unable to work out binary name (PROJ_NAME))
endif
ifeq ($(BOARD),LINUX)
PROJ_NAME=espruino
endif
ifdef DEBUG
#OPTIMIZEFLAGS=-Os -g
OPTIMIZEFLAGS=-g
endif
ifdef PROFILE
OPTIMIZEFLAGS+=-pg
endif
WRAPPERFILE=gen/jswrapper.c
WRAPPERSOURCES = \
src/jswrap_pin.c \
src/jswrap_functions.c \
src/jswrap_modules.c \
src/jswrap_process.c \
src/jswrap_interactive.c \
src/jswrap_json.c \
src/jswrap_object.c \
src/jswrap_string.c \
src/jswrap_array.c \
src/jswrap_arraybuffer.c \
src/jswrap_serial.c \
src/jswrap_spi_i2c.c \
src/jswrap_onewire.c \
src/jswrap_io.c
# it is important that _pin comes before stuff which uses
# integers (as the check for int *includes* the chek for pin)
SOURCES = \
src/jslex.c \
src/jsvar.c \
src/jsutils.c \
src/jsparse.c \
src/jspin.c \
src/jsinteractive.c \
src/jsdevices.c \
$(WRAPPERFILE)
CPPSOURCES =
ifdef BOOTLOADER
ifndef USE_BOOTLOADER
$(error Using bootloader on device that is not expecting one)
endif
BUILD_LINKER_FLAGS+=--bootloader
PROJ_NAME=$(BOOTLOADER_PROJ_NAME)
WRAPPERSOURCES =
SOURCES = \
targets/stm32_boot/main.c \
targets/stm32_boot/utils.c
ifndef DEBUG
OPTIMIZEFLAGS=-Os
endif
else # !BOOTLOADER
ifdef USE_BOOTLOADER
BUILD_LINKER_FLAGS+=--using_bootloader
STM32LOADER_FLAGS+=-p /dev/ttyACM0
BASEADDRESS=$(shell python -c "import sys;sys.path.append('scripts');import common;print hex(0x08000000+common.get_bootloader_size())")
endif
endif
ifdef USB_PRODUCT_ID
DEFINES+=-DUSB_PRODUCT_ID=$(USB_PRODUCT_ID)
endif
ifdef SAVE_ON_FLASH
DEFINES+=-DSAVE_ON_FLASH
endif
ifdef USE_FILESYSTEM
DEFINES += -DUSE_FILESYSTEM
WRAPPERSOURCES += libs/jswrap_fat.c
ifndef LINUX
INCLUDE += -I$(ROOT)/libs/fat_sd
SOURCES += \
libs/fat_sd/fattime.c \
libs/fat_sd/ff.c
#libs/fat_sd/option/ccsbcs.c # for LFN support (see _USE_LFN in ff.h)
ifdef USE_FILESYSTEM_SDIO
DEFINES += -DUSE_FILESYSTEM_SDIO
SOURCES += \
libs/fat_sd/sdio_diskio.c \
libs/fat_sd/sdio_sdcard.c
else #USE_FILESYSTEM_SDIO
SOURCES += \
libs/fat_sd/spi_diskio.c
endif #USE_FILESYSTEM_SDIO
endif #!LINUX
endif #USE_FILESYSTEM
ifdef USE_MATH
DEFINES += -DUSE_MATH
WRAPPERSOURCES += libs/jswrap_math.c
ifndef LINUX
INCLUDE += -I$(ROOT)/libs/math
SOURCES += \
libs/math/acosh.c \
libs/math/asin.c \
libs/math/asinh.c \
libs/math/atan.c \
libs/math/atanh.c \
libs/math/cbrt.c \
libs/math/chbevl.c \
libs/math/clog.c \
libs/math/cmplx.c \
libs/math/const.c \
libs/math/cosh.c \
libs/math/drand.c \
libs/math/exp10.c \
libs/math/exp2.c \
libs/math/exp.c \
libs/math/fabs.c \
libs/math/floor.c \
libs/math/isnan.c \
libs/math/log10.c \
libs/math/log2.c \
libs/math/log.c \
libs/math/mtherr.c \
libs/math/polevl.c \
libs/math/pow.c \
libs/math/powi.c \
libs/math/round.c \
libs/math/setprec.c \
libs/math/sin.c \
libs/math/sincos.c \
libs/math/sindg.c \
libs/math/sinh.c \
libs/math/sqrt.c \
libs/math/tan.c \
libs/math/tandg.c \
libs/math/tanh.c \
libs/math/unity.c
#libs/math/mod2pi.c
#libs/math/mtst.c
#libs/math/dtestvec.c
endif
endif
ifdef USE_GRAPHICS
DEFINES += -DUSE_GRAPHICS
WRAPPERSOURCES += libs/graphics/jswrap_graphics.c
INCLUDE += -I$(ROOT)/libs/graphics
SOURCES += \
libs/graphics/bitmap_font_8x8.c \
libs/graphics/graphics.c \
libs/graphics/lcd_arraybuffer.c \
libs/graphics/lcd_js.c
ifdef USE_LCD_SDL
DEFINES += -DUSE_LCD_SDL
SOURCES += libs/graphics/lcd_sdl.c
LIBS += -lSDL
INCLUDE += -I/usr/include/SDL
endif
ifdef USE_LCD_FSMC
DEFINES += -DUSE_LCD_FSMC
SOURCES += libs/graphics/lcd_fsmc.c
endif
endif
ifdef USE_NET
DEFINES += -DUSE_NET
WRAPPERSOURCES += libs/network/http/jswrap_http.c
INCLUDE += -I$(ROOT)/libs/network/http
SOURCES += \
libs/network/http/httpserver.c
ifdef LINUX
#LIBS += -l...
#INCLUDE += -I...
endif
endif
ifdef USE_CC3000
DEFINES += -DUSE_CC3000 -DSEND_NON_BLOCKING
WRAPPERSOURCES += libs/network/cc3000/jswrap_cc3000.c
INCLUDE += -I$(ROOT)/libs/network/cc3000
SOURCES += \
libs/network/cc3000/board_spi.c \
libs/network/cc3000/cc3000_common.c \
libs/network/cc3000/evnt_handler.c \
libs/network/cc3000/hci.c \
libs/network/cc3000/netapp.c \
libs/network/cc3000/nvmem.c \
libs/network/cc3000/security.c \
libs/network/cc3000/socket.c \
libs/network/cc3000/wlan.c
endif
ifdef USE_TRIGGER
DEFINES += -DUSE_TRIGGER
WRAPPERSOURCES += libs/trigger/jswrap_trigger.c
INCLUDE += -I$(ROOT)/libs/trigger
SOURCES += \
./libs/trigger/trigger.c
endif
ifdef USB
DEFINES += -DUSB
endif
ifeq ($(FAMILY), STM32F1)
ARCHFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m3 -mfix-cortex-m3-ldrd -mthumb-interwork -mfloat-abi=soft
ARM=1
STM32=1
INCLUDE += -I$(ROOT)/targetlibs/stm32f1 -I$(ROOT)/targetlibs/stm32f1/lib
DEFINES += -DSTM32F1
SOURCES += \
targetlibs/stm32f1/lib/misc.c \
targetlibs/stm32f1/lib/stm32f10x_adc.c \
targetlibs/stm32f1/lib/stm32f10x_bkp.c \
targetlibs/stm32f1/lib/stm32f10x_can.c \
targetlibs/stm32f1/lib/stm32f10x_cec.c \
targetlibs/stm32f1/lib/stm32f10x_crc.c \
targetlibs/stm32f1/lib/stm32f10x_dac.c \
targetlibs/stm32f1/lib/stm32f10x_dbgmcu.c \
targetlibs/stm32f1/lib/stm32f10x_dma.c \
targetlibs/stm32f1/lib/stm32f10x_exti.c \
targetlibs/stm32f1/lib/stm32f10x_flash.c \
targetlibs/stm32f1/lib/stm32f10x_fsmc.c \
targetlibs/stm32f1/lib/stm32f10x_gpio.c \
targetlibs/stm32f1/lib/stm32f10x_i2c.c \
targetlibs/stm32f1/lib/stm32f10x_iwdg.c \
targetlibs/stm32f1/lib/stm32f10x_pwr.c \
targetlibs/stm32f1/lib/stm32f10x_rcc.c \
targetlibs/stm32f1/lib/stm32f10x_rtc.c \
targetlibs/stm32f1/lib/stm32f10x_sdio.c \
targetlibs/stm32f1/lib/stm32f10x_spi.c \
targetlibs/stm32f1/lib/stm32f10x_tim.c \
targetlibs/stm32f1/lib/stm32f10x_usart.c \
targetlibs/stm32f1/lib/stm32f10x_wwdg.c \
targetlibs/stm32f1/lib/system_stm32f10x.c
ifdef USB
INCLUDE += -I$(ROOT)/targetlibs/stm32f1/usblib -I$(ROOT)/targetlibs/stm32f1/usb
SOURCES += \
targetlibs/stm32f1/usblib/otgd_fs_cal.c \
targetlibs/stm32f1/usblib/otgd_fs_dev.c \
targetlibs/stm32f1/usblib/otgd_fs_int.c \
targetlibs/stm32f1/usblib/otgd_fs_pcd.c \
targetlibs/stm32f1/usblib/usb_core.c \
targetlibs/stm32f1/usblib/usb_init.c \
targetlibs/stm32f1/usblib/usb_int.c \
targetlibs/stm32f1/usblib/usb_mem.c \
targetlibs/stm32f1/usblib/usb_regs.c \
targetlibs/stm32f1/usblib/usb_sil.c \
targetlibs/stm32f1/usb/usb_desc.c \
targetlibs/stm32f1/usb/usb_endp.c \
targetlibs/stm32f1/usb/usb_istr.c \
targetlibs/stm32f1/usb/usb_prop.c \
targetlibs/stm32f1/usb/usb_pwr.c \
targetlibs/stm32f1/usb/usb_utils.c
endif #USB
endif #STM32F1
ifeq ($(FAMILY), STM32F2)
ARCHFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m3 -mthumb-interwork -mfpu=fpv4-sp-d16 -mfloat-abi=softfp
ARM=1
STM32=1
INCLUDE += -I$(ROOT)/targetlibs/stm32f2 -I$(ROOT)/targetlibs/stm32f2/lib
DEFINES += -DSTM32F2
SOURCES += \
targetlibs/stm32f2/lib/misc.c \
targetlibs/stm32f2/lib/stm32f2xx_adc.c \
targetlibs/stm32f2/lib/stm32f2xx_can.c \
targetlibs/stm32f2/lib/stm32f2xx_crc.c \
targetlibs/stm32f2/lib/stm32f2xx_cryp_aes.c\
targetlibs/stm32f2/lib/stm32f2xx_cryp.c \
targetlibs/stm32f2/lib/stm32f2xx_cryp_des.c\
targetlibs/stm32f2/lib/stm32f2xx_cryp_tdes.c\
targetlibs/stm32f2/lib/stm32f2xx_dac.c \
targetlibs/stm32f2/lib/stm32f2xx_dbgmcu.c \
targetlibs/stm32f2/lib/stm32f2xx_dcmi.c \
targetlibs/stm32f2/lib/stm32f2xx_dma.c \
targetlibs/stm32f2/lib/stm32f2xx_exti.c \
targetlibs/stm32f2/lib/stm32f2xx_flash.c \
targetlibs/stm32f2/lib/stm32f2xx_fsmc.c \
targetlibs/stm32f2/lib/stm32f2xx_gpio.c \
targetlibs/stm32f2/lib/stm32f2xx_hash.c \
targetlibs/stm32f2/lib/stm32f2xx_hash_md5.c \
targetlibs/stm32f2/lib/stm32f2xx_hash_sha1.c \
targetlibs/stm32f2/lib/stm32f2xx_i2c.c \
targetlibs/stm32f2/lib/stm32f2xx_iwdg.c \
targetlibs/stm32f2/lib/stm32f2xx_pwr.c \
targetlibs/stm32f2/lib/stm32f2xx_rcc.c \
targetlibs/stm32f2/lib/stm32f2xx_rng.c \
targetlibs/stm32f2/lib/stm32f2xx_rtc.c \
targetlibs/stm32f2/lib/stm32f2xx_sdio.c \
targetlibs/stm32f2/lib/stm32f2xx_spi.c \
targetlibs/stm32f2/lib/stm32f2xx_syscfg.c \
targetlibs/stm32f2/lib/stm32f2xx_tim.c \
targetlibs/stm32f2/lib/stm32f2xx_usart.c \
targetlibs/stm32f2/lib/stm32f2xx_wwdg.c \
targetlibs/stm32f2/lib/system_stm32f2xx.c
ifdef USB
INCLUDE += -I$(ROOT)/targetlibs/stm32f2/usblib -I$(ROOT)/targetlibs/stm32f2/usb
SOURCES += \
targetlibs/stm32f2/usb/usbd_cdc_vcp.c \
targetlibs/stm32f2/usb/usb_irq_handlers.c \
targetlibs/stm32f2/usb/usbd_desc.c \
targetlibs/stm32f2/usb/usbd_usr.c \
targetlibs/stm32f2/usb/usb_bsp.c \
targetlibs/stm32f2/usblib/usbd_req.c \
targetlibs/stm32f2/usblib/usb_dcd_int.c \
targetlibs/stm32f2/usblib/usbd_core.c \
targetlibs/stm32f2/usblib/usbd_cdc_core.c \
targetlibs/stm32f2/usblib/usbd_ioreq.c \
targetlibs/stm32f2/usblib/usb_core.c \
targetlibs/stm32f2/usblib/usb_dcd.c
#targetlibs/stm32f2/usblib/usb_otg.c \
#targetlibs/stm32f2/usblib/usb_bsp_template.c \
#targetlibs/stm32f2/usblib/usbd_cdc_if_template.c \
#targetlibs/stm32f2/usblib/usb_hcd.c \
#targetlibs/stm32f2/usblib/usb_hcd_int.c
endif #USB
endif #STM32F2
ifeq ($(FAMILY), STM32F3)
ARCHFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork -mfpu=fpv4-sp-d16 -mfloat-abi=softfp
ARM=1
STM32=1
INCLUDE += -I$(ROOT)/targetlibs/stm32f3 -I$(ROOT)/targetlibs/stm32f3/lib
DEFINES += -DSTM32F3
SOURCES += \
targetlibs/stm32f3/lib/stm32f30x_adc.c \
targetlibs/stm32f3/lib/stm32f30x_can.c \
targetlibs/stm32f3/lib/stm32f30x_comp.c \
targetlibs/stm32f3/lib/stm32f30x_crc.c \
targetlibs/stm32f3/lib/stm32f30x_dac.c \
targetlibs/stm32f3/lib/stm32f30x_dbgmcu.c \
targetlibs/stm32f3/lib/stm32f30x_dma.c \
targetlibs/stm32f3/lib/stm32f30x_exti.c \
targetlibs/stm32f3/lib/stm32f30x_flash.c \
targetlibs/stm32f3/lib/stm32f30x_gpio.c \
targetlibs/stm32f3/lib/stm32f30x_i2c.c \
targetlibs/stm32f3/lib/stm32f30x_iwdg.c \
targetlibs/stm32f3/lib/stm32f30x_misc.c \
targetlibs/stm32f3/lib/stm32f30x_opamp.c \
targetlibs/stm32f3/lib/stm32f30x_pwr.c \
targetlibs/stm32f3/lib/stm32f30x_rcc.c \
targetlibs/stm32f3/lib/stm32f30x_rtc.c \
targetlibs/stm32f3/lib/stm32f30x_spi.c \
targetlibs/stm32f3/lib/stm32f30x_syscfg.c \
targetlibs/stm32f3/lib/stm32f30x_tim.c \
targetlibs/stm32f3/lib/stm32f30x_usart.c \
targetlibs/stm32f3/lib/stm32f30x_wwdg.c \
targetlibs/stm32f3/lib/system_stm32f30x.c
ifdef USB
INCLUDE += -I$(ROOT)/targetlibs/stm32f3/usblib -I$(ROOT)/targetlibs/stm32f3/usb
SOURCES += \
targetlibs/stm32f3/usblib/usb_core.c \
targetlibs/stm32f3/usblib/usb_init.c \
targetlibs/stm32f3/usblib/usb_int.c \
targetlibs/stm32f3/usblib/usb_mem.c \
targetlibs/stm32f3/usblib/usb_regs.c \
targetlibs/stm32f3/usblib/usb_sil.c \
targetlibs/stm32f3/usb/usb_desc.c \
targetlibs/stm32f3/usb/usb_endp.c \
targetlibs/stm32f3/usb/usb_istr.c \
targetlibs/stm32f3/usb/usb_prop.c \
targetlibs/stm32f3/usb/usb_pwr.c \
targetlibs/stm32f3/usb/usb_utils.c
endif #USB
endif #STM32F3
ifeq ($(FAMILY), STM32F4)
ARCHFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork -mfpu=fpv4-sp-d16 -mfloat-abi=softfp
ARM=1
STM32=1
INCLUDE += -I$(ROOT)/targetlibs/stm32f4 -I$(ROOT)/targetlibs/stm32f4/lib
DEFINES += -DSTM32F4
SOURCES += \
targetlibs/stm32f4/lib/misc.c \
targetlibs/stm32f4/lib/stm32f4xx_adc.c \
targetlibs/stm32f4/lib/stm32f4xx_can.c \
targetlibs/stm32f4/lib/stm32f4xx_crc.c \
targetlibs/stm32f4/lib/stm32f4xx_cryp_aes.c \
targetlibs/stm32f4/lib/stm32f4xx_cryp.c \
targetlibs/stm32f4/lib/stm32f4xx_cryp_des.c \
targetlibs/stm32f4/lib/stm32f4xx_cryp_tdes.c \
targetlibs/stm32f4/lib/stm32f4xx_dac.c \
targetlibs/stm32f4/lib/stm32f4xx_dbgmcu.c \
targetlibs/stm32f4/lib/stm32f4xx_dcmi.c \
targetlibs/stm32f4/lib/stm32f4xx_dma.c \
targetlibs/stm32f4/lib/stm32f4xx_exti.c \
targetlibs/stm32f4/lib/stm32f4xx_flash.c \
targetlibs/stm32f4/lib/stm32f4xx_fsmc.c \
targetlibs/stm32f4/lib/stm32f4xx_gpio.c \
targetlibs/stm32f4/lib/stm32f4xx_hash.c \
targetlibs/stm32f4/lib/stm32f4xx_hash_md5.c \
targetlibs/stm32f4/lib/stm32f4xx_hash_sha1.c \
targetlibs/stm32f4/lib/stm32f4xx_i2c.c \
targetlibs/stm32f4/lib/stm32f4xx_iwdg.c \
targetlibs/stm32f4/lib/stm32f4xx_pwr.c \
targetlibs/stm32f4/lib/stm32f4xx_rcc.c \
targetlibs/stm32f4/lib/stm32f4xx_rng.c \
targetlibs/stm32f4/lib/stm32f4xx_rtc.c \
targetlibs/stm32f4/lib/stm32f4xx_sdio.c \
targetlibs/stm32f4/lib/stm32f4xx_spi.c \
targetlibs/stm32f4/lib/stm32f4xx_syscfg.c \
targetlibs/stm32f4/lib/stm32f4xx_tim.c \
targetlibs/stm32f4/lib/stm32f4xx_usart.c \
targetlibs/stm32f4/lib/stm32f4xx_wwdg.c \
targetlibs/stm32f4/lib/system_stm32f4xx.c
ifdef USB
INCLUDE += -I$(ROOT)/targetlibs/stm32f4/usblib -I$(ROOT)/targetlibs/stm32f4/usb
SOURCES += \
targetlibs/stm32f4/usblib/usb_core.c \
targetlibs/stm32f4/usblib/usbd_cdc_core.c \
targetlibs/stm32f4/usblib/usb_dcd.c \
targetlibs/stm32f4/usblib/usb_dcd_int.c \
targetlibs/stm32f4/usblib/usbd_core.c \
targetlibs/stm32f4/usblib/usbd_ioreq.c \
targetlibs/stm32f4/usblib/usbd_req.c \
targetlibs/stm32f4/usb/usb_bsp.c \
targetlibs/stm32f4/usb/usbd_cdc_vcp.c \
targetlibs/stm32f4/usb/usbd_desc.c \
targetlibs/stm32f4/usb/usbd_usr.c
#targetlibs/stm32f4/usblib/usb_hcd.c
#targetlibs/stm32f4/usblib/usb_hcd_int.c
#targetlibs/stm32f4/usblib/usb_otg.c
endif #USB
endif #STM32F4
ifdef MBED
ARCHFLAGS += -mcpu=cortex-m3 -mthumb
ARM=1
INCLUDE+=-I$(ROOT)/targetlibs/libmbed -I$(ROOT)/targetlibs/libmbed/$(CHIP) -I$(ROOT)/targetlibs/libmbed/$(CHIP)/GCC_CS
DEFINES += -DMBED
INCLUDE += -I$(ROOT)/targetlibs/mbed
SOURCES += targets/mbed/main.c
CPPSOURCES += targets/mbed/jshardware.cpp
endif
ifdef ARM
LINKER_FILE = gen/linker.ld
DEFINES += -DARM
INCLUDE += -I$(ROOT)/targetlibs/arm
OPTIMIZEFLAGS += -fno-common -fno-exceptions -fdata-sections -ffunction-sections
# -flto -fuse-linker-plugin
# -flto - link time optimisation - could be good for ST's libs
# GCC suggests use of -fuse-linker-plugin with flto
# Does not work - get errors like : `sqrt' referenced in section `.text.asin' of /tmp/ccJheOub.ltrans9.ltrans.o: defined in discarded section `.text' of libs/math/sqrt.o (symbol from plugin)
# 4.6
#export CCPREFIX=arm-linux-gnueabi-
# 4.5
#export CCPREFIX=~/sat/bin/arm-none-eabi-
# 4.4
export CCPREFIX=arm-none-eabi-
endif # ARM
PININFOFILE=$(ROOT)/gen/jspininfo
ifdef PININFOFILE
SOURCES += $(PININFOFILE).c
endif
ifdef CARAMBOLA
TOOLCHAIN_DIR=$(shell cd ~/workspace/carambola/staging_dir/toolchain-*/bin;pwd)
export STAGING_DIR=$(TOOLCHAIN_DIR)
export CCPREFIX=$(TOOLCHAIN_DIR)/mipsel-openwrt-linux-
endif
ifdef RASPBERRYPI
ifneq ($(shell uname -m),armv6l)
# eep. let's cross compile
export CCPREFIX=targetlibs/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-
else
# compiling in-place, so give it a normal name
PROJ_NAME=espruino
endif
endif
ifdef STM32
DEFINES += -DFAKE_STDLIB
# FAKE_STDLIB is for Espruino - it uses its own standard library so we don't have to link in the normal one + get bloated
DEFINES += -DSTM32 -DUSE_STDPERIPH_DRIVER=1 -D$(CHIP) -D$(BOARD) -D$(STLIB)
INCLUDE += -I$(ROOT)/targets/stm32
ifndef BOOTLOADER
SOURCES += \
targets/stm32/main.c \
targets/stm32/jshardware.c \
targets/stm32/stm32_it.c
endif
endif
ifdef LINUX
DEFINES += -DLINUX
INCLUDE += -I$(ROOT)/targets/linux
SOURCES += \
targets/linux/main.c \
targets/linux/jshardware.c
LIBS += -lm # maths lib
endif
SOURCES += $(WRAPPERSOURCES)
SOURCEOBJS = $(SOURCES:.c=.o) $(CPPSOURCES:.cpp=.o)
OBJS = $(SOURCEOBJS) $(PRECOMPILED_OBJS)
# -ffreestanding -nodefaultlibs -nostdlib -fno-common
# -nodefaultlibs -nostdlib -nostartfiles
# -fdata-sections -ffunction-sections are to help remove unused code
CFLAGS += $(OPTIMIZEFLAGS) -c $(ARCHFLAGS) $(DEFINES) $(INCLUDE)
# -Wl,--gc-sections helps remove unused code
# -Wl,--whole-archive checks for duplicates
LDFLAGS += $(OPTIMIZEFLAGS) $(ARCHFLAGS)
ifndef MACOSX
LDFLAGS += -Wl,--gc-sections
endif
ifdef LINKER_FILE
LDFLAGS += -T$(LINKER_FILE)
endif
export CC=$(CCPREFIX)gcc
export LD=$(CCPREFIX)gcc
export AR=$(CCPREFIX)ar
export AS=$(CCPREFIX)as
export OBJCOPY=$(CCPREFIX)objcopy
export OBJDUMP=$(CCPREFIX)objdump
export GDB=$(CCPREFIX)gdb
.PHONY: proj
all: proj
ifeq ($(V),1)
quiet_=
Q=
else
quiet_=quiet_
Q=@
export SILENT=1
endif
$(WRAPPERFILE): scripts/build_jswrapper.py $(WRAPPERSOURCES)
@echo Generating JS wrappers
$(Q)echo WRAPPERSOURCES = $(WRAPPERSOURCES)
$(Q)echo DEFINES = $(DEFINES)
$(Q)python scripts/build_jswrapper.py $(WRAPPERSOURCES) $(DEFINES)
ifdef PININFOFILE
$(PININFOFILE).c $(PININFOFILE).h: scripts/build_pininfo.py
@echo Generating pin info
$(Q)python scripts/build_pininfo.py $(BOARD) $(PININFOFILE).c $(PININFOFILE).h
endif
$(LINKER_FILE): scripts/build_linker.py
@echo Generating linker scripts
$(Q)python scripts/build_linker.py $(BOARD) $(LINKER_FILE) $(BUILD_LINKER_FLAGS)
$(PLATFORM_CONFIG_FILE): boards/$(BOARD).py scripts/build_platform_config.py
@echo Generating platform configs
$(Q)python scripts/build_platform_config.py $(BOARD)
compile=$(CC) $(CFLAGS) $(DEFINES) $< -o $@
link=$(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
obj_dump=$(OBJDUMP) -x -S $(PROJ_NAME).elf > $(PROJ_NAME).lst
obj_to_bin=$(OBJCOPY) -O $1 $(PROJ_NAME).elf $(PROJ_NAME).$2
quiet_compile= CC $@
quiet_link= LD $@
quiet_obj_dump= GEN $(PROJ_NAME).lst
quiet_obj_to_bin= GEN $(PROJ_NAME).$2
%.o: %.c $(PLATFORM_CONFIG_FILE) $(PININFOFILE).h
@echo $($(quiet_)compile)
@$(call compile)
.cpp.o: $(PLATFORM_CONFIG_FILE) $(PININFOFILE).h
@echo $($(quiet_)compile)
@$(call compile)
.s.o:
@echo $($(quiet_)compile)
@$(call compile)
ifdef LINUX # ---------------------------------------------------
proj: $(PLATFORM_CONFIG_FILE) $(PROJ_NAME)
$(PROJ_NAME): $(OBJS)
@echo $($(quiet_)link)
@$(call link)
else # embedded, so generate bin, etc ---------------------------
$(PROJ_NAME).elf: $(OBJS) $(LINKER_FILE)
@echo $($(quiet_)link)
@$(call link)
$(PROJ_NAME).lst : $(PROJ_NAME).elf
@echo $($(quiet_)obj_dump)
@$(call obj_dump)
$(PROJ_NAME).hex: $(PROJ_NAME).elf
@echo $(call $(quiet_)obj_to_bin,ihex,hex)
@$(call obj_to_bin,ihex,hex)
$(PROJ_NAME).srec : $(PROJ_NAME).elf
@echo $(call $(quiet_)obj_to_bin,srec,srec)
@$(call obj_to_bin,srec,srec)
$(PROJ_NAME).bin : $(PROJ_NAME).elf
@echo $(call $(quiet_)obj_to_bin,binary,bin)
@$(call obj_to_bin,binary,bin)
bash scripts/check_size.sh $(PROJ_NAME).bin
proj: $(PROJ_NAME).lst $(PROJ_NAME).bin
#proj: $(PROJ_NAME).lst $(PROJ_NAME).hex $(PROJ_NAME).srec $(PROJ_NAME).bin
flash: all
ifdef OLIMEXINO_STM32_BOOTLOADER
echo Olimexino Serial bootloader
dfu-util -a1 -d 0x1EAF:0x0003 -D $(PROJ_NAME).bin
else
ifdef MBED
cp $(PROJ_NAME).bin /media/MBED;sync
else
echo ST-LINK flash
~/bin/st-flash write $(PROJ_NAME).bin $(BASEADDRESS)
endif
endif
serialflash: all
echo STM32 inbuilt serial bootloader, set BOOT0=1, BOOT1=0
python scripts/stm32loader.py -b 460800 -a $(BASEADDRESS) -ew $(STM32LOADER_FLAGS) $(PROJ_NAME).bin
# python scripts/stm32loader.py -b 460800 -a $(BASEADDRESS) -ewv $(STM32LOADER_FLAGS) $(PROJ_NAME).bin
gdb:
echo "target extended-remote :4242" > gdbinit
echo "file $(PROJ_NAME).elf" >> gdbinit
#echo "load" >> gdbinit
echo "break main" >> gdbinit
echo "break HardFault_Handler" >> gdbinit
$(GDB) -x gdbinit
rm gdbinit
endif # ---------------------------------------------------
clean:
@echo Cleaning targets
$(Q)find . -name *.o | grep -v libmbed | grep -v arm-bcm2708 | xargs rm -f
$(Q)rm -f $(ROOT)/gen/*.c $(ROOT)/gen/*.h $(ROOT)/gen/*.ld
$(Q)rm -f $(PROJ_NAME).elf
$(Q)rm -f $(PROJ_NAME).hex
$(Q)rm -f $(PROJ_NAME).bin
$(Q)rm -f $(PROJ_NAME).srec
$(Q)rm -f $(PROJ_NAME).lst

161
components/external/espruino/README.md vendored Normal file
View File

@@ -0,0 +1,161 @@
Espruino JavaScript for Microcontrollers
========================================
<pre>
_____ _
| __|___ ___ ___ _ _|_|___ ___
| __|_ -| . | _| | | | | . |
|_____|___| _|_| |___|_|_|_|___|
|_|
</pre>
http://www.espruino.com
**NOTE:** This software is beta and is provided as-is, and won't be considered even remotely final until we've released the Espruino Board. As such, don't expect support, and do expect it to change rapidly and without warning. Build your own documentation (see **Building**), as the API may be different from the one described on the Espruino website.
The KickStarter campaign said the Espruino Board will have some things which this repository does not yet have (like working CC3000 support). These are works in progress and should be done by the time you get your board (or will be available as a software update).
About
-----
It'd probably help to read the [FAQ](http://www.espruino.com/FAQ), and specifically the page about [Performance](http://www.espruino.com/Performance) as it contains information about how Espruino itself works.
There's also the auto-generated [Reference](http://www.espruino.com/Reference) for JavaScript commands as well as the [Tutorials](http://www.espruino.com/Tutorials) on the website. However please note that this repository is under heavy development, and the documentation on the Espruino website will match the version [available for download](http://www.espruino.com/Download) but **not** the latest version from Git.
License
-------
Please see the [LICENSE](LICENSE) file
Found a Bug?
------------
Please check that:
* It hasn't [already been found](https://github.com/espruino/Espruino/issues) or [been covered on our forum](www.espruino.com/Forum)
* You're not just looking at outdated documentation (See the [Building](#Building) section to see how to build documentation)
Please [submit bugs](https://github.com/espruino/Espruino/issues) with clear steps to reproduce them (and ideally a test case for the ```tests``` directory), and if at all possible try and include a patch to fix them. Please be aware that we have a whole bunch of outstanding issues (some quite large), so if you report something (especially if it doesn't contain a test or a pull request) it may not be fixed for quite some time.
Contributing
------------
Please see [CONTRIBUTING.md](CONTRIBUTING.md)
Current State
-------------
You can download binaries from http://www.espruino.com/Download (these aren't the latest, but are more likely to work with your board)
Please note that this is BETA. We've been working hard on the Espruino Board support but we haven't had time to check the other boards properly.
* Espruino Board - working
* Linux - working
* STM32VLDISCOVERY - WORKING
* STM32F3DISCOVERY - WORKING
* STM32F4DISCOVERY - WORKING
* STM32F429IDISCOVERY - not working, currently no LCD support
* HY STM32 2.4" - NOT WORKING - appears to crash after startup
* HY STM32 2.8" - WORKING, but screen is not black at startup
* HY STM32 3.2" - WORKING
* Olimexino - WORKING
* Carambola - ?
* Raspberry Pi - WORKING
* Sony SmartWatch - USB VCP support still needed
* MBed platforms - have not worked for a while - hardware wrapper still needed
* Arduino - has never worked. Compiles but doesn't even get past init
* LC-TECH STM32F103RBT6 - WORKING, but with some issues (LED inverted logic, BTN needs pullup to work)
Using
-----
If you're using Espruino for your own personal projects - go ahead, we hope you have fun - and please let us know what you do with it on http://www.espruino.com/Forum!
However if you're planning on selling the Espruino software on your own board, please talk to us:
* Read the terms of the MPLv2 Licence that Espruino is distributed under, and make sure you comply with it
* You won't be able to call your board 'Espruino' but you must explain clearly that it uses 'Espruino' internally (we own the trademark)
* If you're profiting from Espruino without contributing anything back, we won't support you (or your users)
Building
--------
Espruino is easy to build under Linux, and it is possible to build under MacOS. We'd strongly suggest that you DO NOT TRY AND BUILD UNDER WINDOWS, and instead use a Virtual Machine. There's a good post on this here: http://forum.espruino.com/conversations/151
We suggest that you use the CodeSourcery GCC compiler, but paths in Makefile may need changing...
``` BOARDNAME=1 RELEASE=1 make```
* See the top of Makefile for board names
* Without `RELEASE=1`, assertions are kept in the code (which is good for debugging, bad for performance + code size)
* `BOARDNAME=1 RELEASE=1 make serialflash` will flash to /dev/ttyUSB0 using the STM32 serial bootloader (what's needed for Espruino + HY boards)
* `BOARDNAME=1 RELEASE=1 make flash` will flash using st-flash if discovery, or maple bootloader if using that board
You can build documentation by running:
``` python scripts/build_docs.py ```
This will create a file called ```functions.html```
Directories and Files
---------------------
* `ChangeLog`: What's new
* `TODO`: List of things to do
* `boards/`: Information on boards, used to auto-generate a lot of the code
* `code/`: Example JavaScript code
* `gen/`: Auto-Generated Source Files
* `libs/`: Optional libraries to include in Espruino (Math, Filesystem, Graphics, etc)
* `linker/`: Linker files for various processors
* `misc/`: random other stuff
* `scripts/`: Scripts for generating files in gen, and for analysing code/compilation/etc
* `src/`: Main source code
* `targetlibs/`: Libraries for targeted architectures
* `targets/`: Specific code for targeted architectures
* `tests/`: JavaScript Testcases
* `benchmark/`: JavaScript Benchmarks
* `dist_*`: files to be copied into distribution zip file
Adding more devices
-------------------
Currently there are a bunch of different files to modify. Eventually the plan is to fit everything into boards/BOARDNAME.py and to auto-generate the rest of the config files.
* Most build options handled in `Makefile`
* Extra libraries like USB/LCD/filesystem in `Makefile`
* Linker Scripts are in `linker/`
* `boards/*.py` files handle loading the list of available pins so the relevant headers + docs can be created
* Processor-specific code in `targets/stm32`, `targets/linux`, etc.
* Processor-specific libs in `targetlibs/foo`
* `src/jshardware.h` is effectively a simple abstraction layer for SPI/I2C/etc
* `targets/stm32/jshardware.c` also has flash-size-specific defines
* `libs/fat_sd` and `libs/lcd` still have some device-specific defines in too
Adding libraries
-------------------
* Create `jswrap_mylib.c/h` in `libs/`
* Create library functions (see examples in other jswrap files, also the comments in `scripts/common.py`)
Arduino Compile (beta)
----------------------
* Ensure that `targets/arduino/utility` is symlinked to `src`
* Symlink `...arduino_workspace/libraries/Espruino` to `targets/arduino`
Cross Compile for Raspberry Pi
------------------------------
```
cd targetlibs
mkdir raspberrypi
cd raspberrypi
git clone git://github.com/raspberrypi/tools.git
sudo apt-get install ia32-libs
```
Cross Compile for Carambola (OpenWRT)
-------------------------------------
* Follow instructions at <https://github.com/8devices/carambola> to set toolchain up in ```~/workspace/carambola```
* Run ```CARAMBOLA=1 make```

View File

@@ -0,0 +1,2 @@
<EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD>Espruino<EFBFBD><EFBFBD>ֲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>javascript<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>newlib<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>rtconfig.h<>п<EFBFBD><D0BF><EFBFBD>RT_USING_JS<4A><53><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@@ -1,19 +1,58 @@
import rtconfig
Import('RTT_ROOT')
from building import *
import os
cwd = GetCurrentDir()
# source files
src = Split('''
''')
path = [RTT_ROOT + r'/components/external/Espruino']
path = path + [RTT_ROOT + r'/components/external/Espruino/src/']
path = path + [RTT_ROOT + r'/components/external/Espruino/gen/']
path = path + [RTT_ROOT + r'/components/external/Espruino/libs/']
path = path + [RTT_ROOT + r'/components/external/Espruino/targets/rtthread/']
ESPRUINO_SRC_PATH = cwd + '/src'
if GetDepend('RT_USING_JS') and not os.path.exists(ESPRUINO_SRC_PATH):
print '================ERROR============================'
print 'Please get espruino source files and put them under espruino folder'
print '================================================='
exit(0)
src = Split("""
src/jsdevices.c
src/jslex.c
src/jswrap_array.c
src/jswrap_json.c
src/jswrap_process.c
src/jsutils.c
src/jswrap_interactive.c
src/jswrap_onewire.c
src/jswrap_string.c
src/jsparse.c
src/jswrap_arraybuffer.c
src/jswrap_modules.c
src/jswrap_serial.c
src/jsinteractive.c
src/jsvar.c
src/jswrap_io.c
src/jswrap_pin.c
src/jspin.c
src/jswrap_functions.c
src/jswrap_object.c
src/jswrap_spi_i2c.c
"""
)
CPPPATH = [cwd + '/src', cwd + '/gen', cwd + '/libs', cwd + '/targets/rtthread']
group = DefineGroup('Espruino', src, depend = ['RT_USING_JS'], CPPPATH = CPPPATH)
gen = Split("""
gen/jspininfo.c
gen/jswrapper.c
"""
)
target = Split("""
targets/rtthread/espruino.c
targets/rtthread/jshardware.c
"""
)
libs = Split(
"""
libs/jswrap_math.c
"""
)
src += gen + target + libs
group = DefineGroup('Espruino', src, depend = ['RT_USING_JS', 'RT_USING_NEWLIB'], CPPPATH = path)
Return('group')

View File

@@ -0,0 +1,109 @@
Espruino uses a few libraries of code that have been generously given away for
free. Their licences are included below.
-------------------------------------------------------------------------
FATFS
-------------------------------------------------------------------------
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module include file R0.07c (C)ChaN, 2009
/----------------------------------------------------------------------------/
/ FatFs module is an open source software to implement FAT file system to
/ small embedded systems. This is a free software and is opened for education,
/ research and commercial developments under license policy of following terms.
/
/ Copyright (C) 2009, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/ personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.*/
-------------------------------------------------------------------------
FATFS to SPI bridge
-------------------------------------------------------------------------
/* Copyright (c) 2009, Martin Thomas, ChaN
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. */
-------------------------------------------------------------------------
FATFS to SDIO bridge
-------------------------------------------------------------------------
/* author: ickle */ - No details given with source code. If you have
anything you'd like to include, pleas e-mail us and let us know.
-------------------------------------------------------------------------
8x8 LCD Font
-------------------------------------------------------------------------
/*
http://forum.osdev.org/viewtopic.php?f=2&t=22033
Created Sunday, May 23, 2010 by Quinn Evans
Renamed and updated Monday 24, 2010
This font (Vincent) is released by me into the public domain. I claim no
copyright, and hereby make this software available to the public for any use,
at any time, free of restrictions, legal or otherwise.
*/
-------------------------------------------------------------------------
CC3000 Host Driver Implementation.
-------------------------------------------------------------------------
Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the
distribution.
Neither the name of Texas Instruments Incorporated nor the names of
its contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,57 @@
_____ _
| __|___ ___ ___ _ _|_|___ ___
| __|_ -| . | _| | | | | . |
|_____|___| _|_| |___|_|_|_|___|
|_|
Copyright 2013 Gordon Williams
http://www.espruino.com
--------------------------------------------------------------
There are a few different binaries in this ZIP file, for different
types of Microcontroller:
espruino_#v##_hystm32_24_ve.bin
- 'HY'STM32F103VET6 ARM with 2.4" LCD display
This is available from eBay
espruino_#v##_hystm32_28_rb.bin
- 'HY'STM32F103RBT6 ARM with 2.8" LCD display
This is available from eBay
espruino_#v##_hystm32_32_vc.bin
- 'HY'STM32F103VCT6 ARM with 3.2" LCD display
This is available from eBay
espruino_#v##_olimexino_stm32.bin
- You will need to overwrite the Maple bootloader to install this.
Espruino is now too large to fit in flash alongside it.
- Olimexino-STM32 Arduino form factor board
- Leaf Labs Maple Arduino form factor board
espruino_#v##_stm32vldiscovery.bin
- STM32VLDISCOVERY board
espruino_#v##_stm32f3discovery.bin
- STM32F3DISCOVERY board
espruino_#v##_stm32f4discovery.bin
- STM32F4DISCOVERY board
espruino_#v##_raspberrypi
- Raspberry Pi executable (just copy it to the device and run it)
NOTE: There is GPIO support (which requires you to run Espruino as root)
however there is no Serial, SPI, OneWire or I2C support at the moment so
you're pretty limited!
For information on devices, and on how to flash these binary files on to
each device, please see our website, http://www.espruino.com
NOTES:
* On the STM32F4DISCOVERY the default USART is USART2 (because
USART1 shares some pins with USB). This means you must connect
serial connections to PA2/PA3 NOT PA9/PA10 as you would for
the STM32VLDISCOVERY.

View File

@@ -0,0 +1 @@
This directory contains auto-generated files

View File

@@ -0,0 +1,7 @@
// auto-generated pin info file
// for board LINUX
#include "jspininfo.h"
const JshPinInfo pinInfo[JSH_PIN_COUNT] = {
};

View File

@@ -0,0 +1,39 @@
// auto-generated pin info file
// for board LINUX
#ifndef __JSPININFO_H_
#define __JSPININFO_H_
#include "jspin.h"
#define JSH_PIN_COUNT 0
#define JSH_PORTA_COUNT 0
#define JSH_PORTB_COUNT 0
#define JSH_PORTC_COUNT 0
#define JSH_PORTD_COUNT 0
#define JSH_PORTE_COUNT 0
#define JSH_PORTF_COUNT 0
#define JSH_PORTG_COUNT 0
#define JSH_PORTH_COUNT 0
#define JSH_PORTA_OFFSET -1
#define JSH_PORTB_OFFSET -1
#define JSH_PORTC_OFFSET -1
#define JSH_PORTD_OFFSET -1
#define JSH_PORTE_OFFSET -1
#define JSH_PORTF_OFFSET -1
#define JSH_PORTG_OFFSET -1
#define JSH_PORTH_OFFSET -1
#define JSH_PININFO_FUNCTIONS 0
typedef struct JshPinInfo {
JsvPinInfoPort port;
JsvPinInfoPin pin;
JsvPinInfoAnalog analog; // TODO: maybe we don't need to store analogs separately
JshPinFunction functions[JSH_PININFO_FUNCTIONS];
} PACKED_FLAGS JshPinInfo;
extern const JshPinInfo pinInfo[JSH_PIN_COUNT];
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,53 @@
// Automatically generated header file for LINUX
// Generated by scripts/build_platform_config.py
#ifndef _PLATFORM_CONFIG_H
#define _PLATFORM_CONFIG_H
#include <rtthread.h>
#define PC_BOARD_ID "LINUX"
#define PC_BOARD_CHIP "LINUX"
#define PC_BOARD_CHIP_FAMILY "LINUX"
// SYSTICK is the counter that counts up and that we use as the real-time clock
// The smaller this is, the longer we spend in interrupts, but also the more we can sleep!
#define SYSTICK_RANGE 0x1000000 // the Maximum (it is a 24 bit counter) - on Olimexino this is about 0.6 sec
#define SYSTICKS_BEFORE_USB_DISCONNECT 2
#define DEFAULT_BUSY_PIN_INDICATOR (Pin)-1 // no indicator
#define DEFAULT_SLEEP_PIN_INDICATOR (Pin)-1 // no indicator
// When to send the message that the IO buffer is getting full
#define IOBUFFER_XOFF ((TXBUFFERMASK)*6/8)
// When to send the message that we can start receiving again
#define IOBUFFER_XON ((TXBUFFERMASK)*3/8)
#define RAM_TOTAL (-1*1024)
#define FLASH_TOTAL (-1*1024)
#define RESIZABLE_JSVARS // Allocate variables in blocks using malloc
#define USARTS 0
#define SPIS 1
#define I2CS 0
#define ADCS 0
#define DACS 0
#define DEFAULT_CONSOLE_DEVICE EV_USBSERIAL
#define IOBUFFERMASK 31 // (max 255) amount of items in event buffer - events take ~9 bytes each
#define TXBUFFERMASK 31 // (max 255)
// definition to avoid compilation when Pin/platform config is not defined
#define IS_PIN_USED_INTERNALLY(PIN) ((false))
#define IS_PIN_A_LED(PIN) ((false))
#define IS_PIN_A_BUTTON(PIN) ((false))
#endif // _PLATFORM_CONFIG_H

View File

@@ -0,0 +1,233 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* This file is designed to be parsed during the build process
*
* Contains built-in functions for Maths
* ----------------------------------------------------------------------------
*/
#include "jswrap_math.h"
/*JSON{ "type":"class",
"class" : "Math",
"description" : "This is a standard JavaScript class that contains useful Maths routines"
}*/
// -------------------------------------------------------------------- Integer
/*JSON{ "type":"staticmethod",
"class" : "Integer", "name" : "valueOf",
"generate" : "jswrap_integer_valueOf",
"description" : "Given a string containing a single character, return the numeric value of it",
"params" : [ [ "character" ,"JsVar", "A string containing a single character"] ],
"return" : ["int", "The integer value of char"]
}*/
JsVarInt jswrap_integer_valueOf(JsVar *v) {
if (!jsvIsString(v) || jsvGetStringLength(v)!=1)
return 0;
return (int)v->varData.str[0];
}
/*JSON{ "type":"variable", "name" : "NaN",
"generate_full" : "NAN",
"return" : ["float", "Not a Number"]
}*/
// -------------------------------------------------------------------- Double
/*JSON{ "type":"staticmethod",
"class" : "Double", "name" : "doubleToIntBits",
"generate_full" : "*(JsVarInt*)&x",
"description" : " Convert the floating point value given into an integer representing the bits contained in it",
"params" : [ [ "x", "float", "A floating point number"] ],
"return" : ["int", "The integer representation of x"]
}*/
// -------------------------------------------------------------------- Math
/*JSON{ "type":"staticproperty",
"class" : "Math", "name" : "E",
"generate_full" : "2.71828182846",
"return" : ["float", "The value of E - 2.71828182846"]
}*/
/*JSON{ "type":"staticproperty",
"class" : "Math", "name" : "PI",
"generate_full" : "3.14159265359",
"return" : ["float", "The value of PI - 3.14159265359"]
}*/
/*JSON{ "type":"staticmethod",
"class" : "Math", "name" : "abs",
"generate" : "jswrap_math_abs",
"params" : [ [ "x", "float", "A floating point value"] ],
"return" : ["float", "The absolute value of x (eg, ```Math.abs(2)==2```, but also ```Math.abs(-2)==2```)"]
}*/
JsVarFloat jswrap_math_abs(JsVarFloat x) {
return (x<0)?-x:x;
}
/*JSON{ "type":"staticmethod",
"class" : "Math", "name" : "acos",
"generate" : "acos",
"params" : [ [ "x", "float", "The value to get the arc cosine of"] ],
"return" : ["float", "The arc cosine of x, between 0 and PI"]
}*/
/*JSON{ "type":"staticmethod",
"class" : "Math", "name" : "asin",
"generate" : "asin",
"params" : [ [ "x", "float", "The value to get the arc sine of"] ],
"return" : ["float", "The arc sine of x, between -PI/2 and PI/2"]
}*/
/*JSON{ "type":"staticmethod",
"class" : "Math", "name" : "atan",
"generate" : "atan",
"params" : [ [ "x", "float", "The value to get the arc tangent of"] ],
"return" : ["float", "The arc tangent of x, between -PI/2 and PI/2"]
}*/
/*JSON{ "type":"staticmethod",
"class" : "Math", "name" : "atan2",
"generate" : "atan2",
"params" : [ [ "y", "float", "The Y-part of the angle to get the arc tangent of"],
[ "x", "float", "The X-part of the angle to get the arc tangent of"] ],
"return" : ["float", "The arctangent of Y/X, between -PI and PI"]
}*/
/* we use sin here, not cos, to try and save a bit of code space */
/*JSON{ "type":"staticmethod",
"class" : "Math", "name" : "cos",
"generate_full" : "sin(jsvGetFloat(theta) + (3.14159265359/2.0))",
"params" : [ [ "theta", "float", "The angle to get the cosine of"] ],
"return" : ["float", "The cosine of theta"]
}*/
#define DBL_MAX 1.7976931348623157E+308
double fs_fmod(double x, double y)
{
double a, b;
const double c = x;
if (0 > c) {
x = -x;
}
if (0 > y) {
y = -y;
}
if (y != 0 && DBL_MAX >= y && DBL_MAX >= x) {
while (x >= y) {
a = x / 2;
b = y;
while (a >= b) {
b *= 2;
}
x -= b;
}
} else {
x = 0;
}
return 0 > c ? -x : x;
}
double jswrap_math_pow(double x, double y)
{
double p;
if (0 > x && fs_fmod(y, 1) == 0) {
if (fs_fmod(y, 2) == 0) {
p = exp(log(-x) * y);
} else {
p = -exp(log(-x) * y);
}
} else {
if (x != 0 || 0 >= y) {
p = exp(log( x) * y);
} else {
p = 0;
}
}
return p;
}
/*JSON{ "type":"staticmethod",
"class" : "Math", "name" : "pow",
"generate" : "jswrap_math_pow",
"params" : [ [ "x", "float", "The value to raise to the power"],
[ "y", "float", "The power x should be raised to"] ],
"return" : ["float", "x raised to the power y (x^y)"]
}*/
/*JSON{ "type":"staticmethod",
"class" : "Math", "name" : "random",
"generate_full" : "(JsVarFloat)rand() / (JsVarFloat)RAND_MAX",
"return" : ["float", "A random number between 0 and 1"]
}*/
/*JSON{ "type":"staticmethod",
"class" : "Math", "name" : "round",
"generate" : "(JsVarInt)round",
"params" : [ [ "x", "float", "The value to round"] ],
"return" : ["int", "x, rounded to the nearest integer"]
}*/
/*JSON{ "type":"staticmethod",
"class" : "Math", "name" : "sin",
"generate" : "sin",
"params" : [ [ "theta", "float", "The angle to get the sine of"] ],
"return" : ["float", "The sine of theta"]
}*/
/* we could use the real sqrt - but re-use pow to save on code space */
/*JSON{ "type":"staticmethod",
"class" : "Math", "name" : "sqrt",
"generate_full" : "jswrap_math_pow(jsvGetFloat(x),0.5)",
"params" : [ [ "x", "float", "The value to take the square root of"] ],
"return" : ["float", "The square root of x"]
}*/
/*JSON{ "type":"staticmethod",
"class" : "Math", "name" : "ceil",
"generate" : "ceil",
"params" : [ [ "x", "float", "The value to round up"] ],
"return" : ["float", "x, rounded upwards to the nearest integer"]
}*/
/*JSON{ "type":"staticmethod",
"class" : "Math", "name" : "floor",
"generate" : "floor",
"params" : [ [ "x", "float", "The value to round down"] ],
"return" : ["float", "x, rounded downwards to the nearest integer"]
}*/
/*JSON{ "type":"staticmethod",
"class" : "Math", "name" : "exp",
"generate" : "exp",
"params" : [ [ "x", "float", "The value raise E to the power of"] ],
"return" : ["float", "E^x"]
}*/
/*JSON{ "type":"staticmethod",
"class" : "Math", "name" : "log",
"generate" : "log",
"params" : [ [ "x", "float", "The value to take the logarithm (base E) root of"] ],
"return" : ["float", "The log (base E) of x"]
}*/
/*JSON{ "type":"staticmethod", "ifndef" : "SAVE_ON_FLASH",
"class" : "Math", "name" : "clip",
"generate" : "jswrap_math_clip",
"description" : "Clip a number to be between min and max (inclusive)",
"params" : [ [ "x", "float", "A floating point value to clip"],
[ "min", "float", "The smallest the value should be"],
[ "max", "float", "The largest the value should be"] ],
"return" : ["float", "The value of x, clipped so as not to be below min or above max."]
}*/
JsVarFloat jswrap_math_clip(JsVarFloat x, JsVarFloat min, JsVarFloat max) {
if (x<min) x=min;
if (x>max) x=max;
return x;
}
/*JSON{ "type":"staticmethod", "ifndef" : "SAVE_ON_FLASH",
"class" : "Math", "name" : "wrap",
"generate" : "wrapAround",
"description" : "Wrap a number around if it is less than 0 or greater than or equal to max. For instance you might do: ```Math.wrap(angleInDegrees, 360)```",
"params" : [ [ "x", "float", "A floating point value to wrap"],
[ "max", "float", "The largest the value should be"] ],
"return" : ["float", "The value of x, wrapped so as not to be below min or above max."]
}*/

View File

@@ -0,0 +1,28 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* Contains built-in functions for Maths
* ----------------------------------------------------------------------------
*/
#include "jsutils.h"
#include "jsvar.h"
#ifdef ARM
#include "mconf.h"
#include "protos.h"
#else
#include <math.h>
#endif
JsVarInt jswrap_integer_valueOf(JsVar *v);
JsVarFloat jswrap_math_abs(JsVarFloat x);
double jswrap_math_pow(double x, double y);
JsVarFloat jswrap_math_clip(JsVarFloat x, JsVarFloat min, JsVarFloat max);

View File

@@ -0,0 +1,32 @@
This suite of C language elementary functions offers support for
not-a-number (NaN) and infinity rules, subnormal numbers, and minus
zero as described by IEEE standard 754 and the Numerical C Extensions
Group (NCEG). For a variety of reasons, many computers cannot take
advantage of these features. You can disable any or all of them by
removing the corresponding preprocessor macros. Check the files
mconf.h and const.c carefully to be sure they are appropriate for your
system.
------------------------------------------
http://www.netlib.org/cephes/readme
Some software in this archive may be from the book _Methods and
Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
International, 1989) or from the Cephes Mathematical Library, a
commercial product. In either event, it is copyrighted by the author.
What you see here may be used freely but it comes with no support or
guarantee.
The two known misprints in the book are repaired here in the
source listings for the gamma function and the incomplete beta
integral.
Stephen L. Moshier
moshier@na-net.ornl.gov

View File

@@ -0,0 +1,167 @@
/* acosh.c
*
* Inverse hyperbolic cosine
*
*
*
* SYNOPSIS:
*
* double x, y, acosh();
*
* y = acosh( x );
*
*
*
* DESCRIPTION:
*
* Returns inverse hyperbolic cosine of argument.
*
* If 1 <= x < 1.5, a rational approximation
*
* sqrt(z) * P(z)/Q(z)
*
* where z = x-1, is used. Otherwise,
*
* acosh(x) = log( x + sqrt( (x-1)(x+1) ).
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC 1,3 30000 4.2e-17 1.1e-17
* IEEE 1,3 30000 4.6e-16 8.7e-17
*
*
* ERROR MESSAGES:
*
* message condition value returned
* acosh domain |x| < 1 NAN
*
*/
/* acosh.c */
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
*/
/* acosh(z) = sqrt(x) * R(x), z = x + 1, interval 0 < x < 0.5 */
#include "mconf.h"
#ifdef UNK
const static double P[] = {
1.18801130533544501356E2,
3.94726656571334401102E3,
3.43989375926195455866E4,
1.08102874834699867335E5,
1.10855947270161294369E5
};
const static double Q[] = {
/* 1.00000000000000000000E0,*/
1.86145380837903397292E2,
4.15352677227719831579E3,
2.97683430363289370382E4,
8.29725251988426222434E4,
7.83869920495893927727E4
};
#endif
#ifdef DEC
static unsigned short P[] = {
0041755,0115055,0144002,0146444,
0043166,0132103,0155150,0150302,
0044006,0057360,0003021,0162753,
0044323,0021557,0175225,0056253,
0044330,0101771,0040046,0006636
};
static unsigned short Q[] = {
/*0040200,0000000,0000000,0000000,*/
0042072,0022467,0126670,0041232,
0043201,0146066,0152142,0034015,
0043750,0110257,0121165,0026100,
0044242,0007103,0034667,0033173,
0044231,0014576,0175573,0017472
};
#endif
#ifdef IBMPC
static unsigned short P[] = {
0x59a4,0xb900,0xb345,0x405d,
0x1a18,0x7b4d,0xd688,0x40ae,
0x3cbd,0x00c2,0xcbde,0x40e0,
0xab95,0xff52,0x646d,0x40fa,
0xc1b4,0x2804,0x107f,0x40fb
};
static unsigned short Q[] = {
/*0x0000,0x0000,0x0000,0x3ff0,*/
0x0853,0xf5b7,0x44a6,0x4067,
0x4702,0xda8c,0x3986,0x40b0,
0xa588,0xf44e,0x1215,0x40dd,
0xe6cf,0x6736,0x41c8,0x40f4,
0x63e7,0xdf6f,0x232f,0x40f3
};
#endif
#ifdef MIEEE
static unsigned short P[] = {
0x405d,0xb345,0xb900,0x59a4,
0x40ae,0xd688,0x7b4d,0x1a18,
0x40e0,0xcbde,0x00c2,0x3cbd,
0x40fa,0x646d,0xff52,0xab95,
0x40fb,0x107f,0x2804,0xc1b4
};
static unsigned short Q[] = {
0x4067,0x44a6,0xf5b7,0x0853,
0x40b0,0x3986,0xda8c,0x4702,
0x40dd,0x1215,0xf44e,0xa588,
0x40f4,0x41c8,0x6736,0xe6cf,
0x40f3,0x232f,0xdf6f,0x63e7,
};
#endif
#ifdef ANSIPROT
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
extern double log ( double );
extern double sqrt ( double );
#else
double log(), sqrt(), polevl(), p1evl();
#endif
extern double LOGE2, INFINITY, NAN;
double acosh(x)
double x;
{
double a, z;
if( x < 1.0 )
{
mtherr( "acosh", DOMAIN );
return(NAN);
}
if( x > 1.0e8 )
{
#ifdef INFINITIES
if( x == INFINITY )
return( INFINITY );
#endif
return( log(x) + LOGE2 );
}
z = x - 1.0;
if( z < 0.5 )
{
a = sqrt(z) * (polevl(z, P, 4) / p1evl(z, Q, 5) );
return( a );
}
a = sqrt( z*(x+1.0) );
return( log(x + a) );
}

View File

@@ -0,0 +1,324 @@
/* asin.c
*
* Inverse circular sine
*
*
*
* SYNOPSIS:
*
* double x, y, asin();
*
* y = asin( x );
*
*
*
* DESCRIPTION:
*
* Returns radian angle between -pi/2 and +pi/2 whose sine is x.
*
* A rational function of the form x + x**3 P(x**2)/Q(x**2)
* is used for |x| in the interval [0, 0.5]. If |x| > 0.5 it is
* transformed by the identity
*
* asin(x) = pi/2 - 2 asin( sqrt( (1-x)/2 ) ).
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC -1, 1 40000 2.6e-17 7.1e-18
* IEEE -1, 1 10^6 1.9e-16 5.4e-17
*
*
* ERROR MESSAGES:
*
* message condition value returned
* asin domain |x| > 1 NAN
*
*/
/* acos()
*
* Inverse circular cosine
*
*
*
* SYNOPSIS:
*
* double x, y, acos();
*
* y = acos( x );
*
*
*
* DESCRIPTION:
*
* Returns radian angle between 0 and pi whose cosine
* is x.
*
* Analytically, acos(x) = pi/2 - asin(x). However if |x| is
* near 1, there is cancellation error in subtracting asin(x)
* from pi/2. Hence if x < -0.5,
*
* acos(x) = pi - 2.0 * asin( sqrt((1+x)/2) );
*
* or if x > +0.5,
*
* acos(x) = 2.0 * asin( sqrt((1-x)/2) ).
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC -1, 1 50000 3.3e-17 8.2e-18
* IEEE -1, 1 10^6 2.2e-16 6.5e-17
*
*
* ERROR MESSAGES:
*
* message condition value returned
* asin domain |x| > 1 NAN
*/
/* asin.c */
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
/* arcsin(x) = x + x^3 P(x^2)/Q(x^2)
0 <= x <= 0.625
Peak relative error = 1.2e-18 */
#if UNK
const static double P[6] = {
4.253011369004428248960E-3,
-6.019598008014123785661E-1,
5.444622390564711410273E0,
-1.626247967210700244449E1,
1.956261983317594739197E1,
-8.198089802484824371615E0,
};
const static double Q[5] = {
/* 1.000000000000000000000E0, */
-1.474091372988853791896E1,
7.049610280856842141659E1,
-1.471791292232726029859E2,
1.395105614657485689735E2,
-4.918853881490881290097E1,
};
#endif
#if DEC
static short P[24] = {
0036213,0056330,0057244,0053234,
0140032,0015011,0114762,0160255,
0040656,0035130,0136121,0067313,
0141202,0014616,0170474,0101731,
0041234,0100076,0151674,0111310,
0141003,0025540,0033165,0077246,
};
static short Q[20] = {
/* 0040200,0000000,0000000,0000000, */
0141153,0155310,0055360,0072530,
0041614,0177001,0027764,0101237,
0142023,0026733,0064653,0133266,
0042013,0101264,0023775,0176351,
0141504,0140420,0050660,0036543,
};
#endif
#if IBMPC
static short P[24] = {
0x8ad3,0x0bd4,0x6b9b,0x3f71,
0x5c16,0x333e,0x4341,0xbfe3,
0x2dd9,0x178a,0xc74b,0x4015,
0x907b,0xde27,0x4331,0xc030,
0x9259,0xda77,0x9007,0x4033,
0xafd5,0x06ce,0x656c,0xc020,
};
static short Q[20] = {
/* 0x0000,0x0000,0x0000,0x3ff0, */
0x0eab,0x0b5e,0x7b59,0xc02d,
0x9054,0x25fe,0x9fc0,0x4051,
0x76d7,0x6d35,0x65bb,0xc062,
0xbf9d,0x84ff,0x7056,0x4061,
0x07ac,0x0a36,0x9822,0xc048,
};
#endif
#if MIEEE
static short P[24] = {
0x3f71,0x6b9b,0x0bd4,0x8ad3,
0xbfe3,0x4341,0x333e,0x5c16,
0x4015,0xc74b,0x178a,0x2dd9,
0xc030,0x4331,0xde27,0x907b,
0x4033,0x9007,0xda77,0x9259,
0xc020,0x656c,0x06ce,0xafd5,
};
static short Q[20] = {
/* 0x3ff0,0x0000,0x0000,0x0000, */
0xc02d,0x7b59,0x0b5e,0x0eab,
0x4051,0x9fc0,0x25fe,0x9054,
0xc062,0x65bb,0x6d35,0x76d7,
0x4061,0x7056,0x84ff,0xbf9d,
0xc048,0x9822,0x0a36,0x07ac,
};
#endif
/* arcsin(1-x) = pi/2 - sqrt(2x)(1+R(x))
0 <= x <= 0.5
Peak relative error = 4.2e-18 */
#if UNK
const static double R[5] = {
2.967721961301243206100E-3,
-5.634242780008963776856E-1,
6.968710824104713396794E0,
-2.556901049652824852289E1,
2.853665548261061424989E1,
};
const static double S[4] = {
/* 1.000000000000000000000E0, */
-2.194779531642920639778E1,
1.470656354026814941758E2,
-3.838770957603691357202E2,
3.424398657913078477438E2,
};
#endif
#if DEC
static short R[20] = {
0036102,0077034,0142164,0174103,
0140020,0036222,0147711,0044173,
0040736,0177655,0153631,0171523,
0141314,0106525,0060015,0055474,
0041344,0045422,0003630,0040344,
};
static short S[16] = {
/* 0040200,0000000,0000000,0000000, */
0141257,0112425,0132772,0166136,
0042023,0010315,0075523,0175020,
0142277,0170104,0126203,0017563,
0042253,0034115,0102662,0022757,
};
#endif
#if IBMPC
static short R[20] = {
0x9f08,0x988e,0x4fc3,0x3f68,
0x290f,0x59f9,0x0792,0xbfe2,
0x3e6a,0xbaf3,0xdff5,0x401b,
0xab68,0xac01,0x91aa,0xc039,
0x081d,0x40f3,0x8962,0x403c,
};
static short S[16] = {
/* 0x0000,0x0000,0x0000,0x3ff0, */
0x5d8c,0xb6bf,0xf2a2,0xc035,
0x7f42,0xaf6a,0x6219,0x4062,
0x63ee,0x9590,0xfe08,0xc077,
0x44be,0xb0b6,0x6709,0x4075,
};
#endif
#if MIEEE
static short R[20] = {
0x3f68,0x4fc3,0x988e,0x9f08,
0xbfe2,0x0792,0x59f9,0x290f,
0x401b,0xdff5,0xbaf3,0x3e6a,
0xc039,0x91aa,0xac01,0xab68,
0x403c,0x8962,0x40f3,0x081d,
};
static short S[16] = {
/* 0x3ff0,0x0000,0x0000,0x0000, */
0xc035,0xf2a2,0xb6bf,0x5d8c,
0x4062,0x6219,0xaf6a,0x7f42,
0xc077,0xfe08,0x9590,0x63ee,
0x4075,0x6709,0xb0b6,0x44be,
};
#endif
/* pi/2 = PIO2 + MOREBITS. */
#ifdef DEC
#define MOREBITS 5.721188726109831840122E-18
#else
#define MOREBITS 6.123233995736765886130E-17
#endif
#ifdef ANSIPROT
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
extern double sqrt ( double );
double asin ( double );
#else
double sqrt(), polevl(), p1evl();
double asin();
#endif
extern double PIO2, PIO4, NAN;
double asin(x)
double x;
{
double a, p, z, zz;
short sign;
if( x > 0 )
{
sign = 1;
a = x;
}
else
{
sign = -1;
a = -x;
}
if( a > 1.0 )
{
mtherr( "asin", DOMAIN );
return( NAN );
}
if( a > 0.625 )
{
/* arcsin(1-x) = pi/2 - sqrt(2x)(1+R(x)) */
zz = 1.0 - a;
p = zz * polevl( zz, R, 4)/p1evl( zz, S, 4);
zz = sqrt(zz+zz);
z = PIO4 - zz;
zz = zz * p - MOREBITS;
z = z - zz;
z = z + PIO4;
}
else
{
if( a < 1.0e-8 )
{
return(x);
}
zz = a * a;
z = zz * polevl( zz, P, 5)/p1evl( zz, Q, 5);
z = a * z + a;
}
if( sign < 0 )
z = -z;
return(z);
}
double acos(x)
double x;
{
double z;
if( (x < -1.0) || (x > 1.0) )
{
mtherr( "acos", DOMAIN );
return( NAN );
}
if( x > 0.5 )
{
return( 2.0 * asin( sqrt(0.5 - 0.5*x) ) );
}
z = PIO4 - asin(x);
z = z + MOREBITS;
z = z + PIO4;
return( z );
}

View File

@@ -0,0 +1,165 @@
/* asinh.c
*
* Inverse hyperbolic sine
*
*
*
* SYNOPSIS:
*
* double x, y, asinh();
*
* y = asinh( x );
*
*
*
* DESCRIPTION:
*
* Returns inverse hyperbolic sine of argument.
*
* If |x| < 0.5, the function is approximated by a rational
* form x + x**3 P(x)/Q(x). Otherwise,
*
* asinh(x) = log( x + sqrt(1 + x*x) ).
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC -3,3 75000 4.6e-17 1.1e-17
* IEEE -1,1 30000 3.7e-16 7.8e-17
* IEEE 1,3 30000 2.5e-16 6.7e-17
*
*/
/* asinh.c */
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
#ifdef UNK
const static double P[] = {
-4.33231683752342103572E-3,
-5.91750212056387121207E-1,
-4.37390226194356683570E0,
-9.09030533308377316566E0,
-5.56682227230859640450E0
};
const static double Q[] = {
/* 1.00000000000000000000E0,*/
1.28757002067426453537E1,
4.86042483805291788324E1,
6.95722521337257608734E1,
3.34009336338516356383E1
};
#endif
#ifdef DEC
static unsigned short P[] = {
0136215,0173033,0110410,0105475,
0140027,0076361,0020056,0164520,
0140613,0173401,0160136,0053142,
0141021,0070744,0000503,0176261,
0140662,0021550,0073106,0133351
};
static unsigned short Q[] = {
/* 0040200,0000000,0000000,0000000,*/
0041116,0001336,0034120,0173054,
0041502,0065300,0013144,0021231,
0041613,0022376,0035516,0153063,
0041405,0115216,0054265,0004557
};
#endif
#ifdef IBMPC
static unsigned short P[] = {
0x1168,0x7221,0xbec3,0xbf71,
0xdd2a,0x2405,0xef9e,0xbfe2,
0xcacc,0x3c0b,0x7ee0,0xc011,
0x7f96,0x8028,0x2e3c,0xc022,
0xd6dd,0x0ec8,0x446d,0xc016
};
static unsigned short Q[] = {
/* 0x0000,0x0000,0x0000,0x3ff0,*/
0x1ec5,0xc70a,0xc05b,0x4029,
0x8453,0x02cc,0x4d58,0x4048,
0xdac6,0xc769,0x649f,0x4051,
0xa12e,0xcb16,0xb351,0x4040
};
#endif
#ifdef MIEEE
static unsigned short P[] = {
0xbf71,0xbec3,0x7221,0x1168,
0xbfe2,0xef9e,0x2405,0xdd2a,
0xc011,0x7ee0,0x3c0b,0xcacc,
0xc022,0x2e3c,0x8028,0x7f96,
0xc016,0x446d,0x0ec8,0xd6dd
};
static unsigned short Q[] = {
0x4029,0xc05b,0xc70a,0x1ec5,
0x4048,0x4d58,0x02cc,0x8453,
0x4051,0x649f,0xc769,0xdac6,
0x4040,0xb351,0xcb16,0xa12e
};
#endif
#ifdef ANSIPROT
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
extern double sqrt ( double );
extern double log ( double );
#else
double log(), sqrt(), polevl(), p1evl();
#endif
extern double LOGE2, INFINITY;
double asinh(xx)
double xx;
{
double a, z, x;
int sign;
#ifdef MINUSZERO
if( xx == 0.0 )
return(xx);
#endif
if( xx < 0.0 )
{
sign = -1;
x = -xx;
}
else
{
sign = 1;
x = xx;
}
if( x > 1.0e8 )
{
#ifdef INFINITIES
if( x == INFINITY )
return(xx);
#endif
return( sign * (log(x) + LOGE2) );
}
z = x * x;
if( x < 0.5 )
{
a = ( polevl(z, P, 4)/p1evl(z, Q, 4) ) * z;
a = a * x + x;
if( sign < 0 )
a = -a;
return(a);
}
a = sqrt( z + 1.0 );
return( sign * log(x + a) );
}

View File

@@ -0,0 +1,393 @@
/* atan.c
*
* Inverse circular tangent
* (arctangent)
*
*
*
* SYNOPSIS:
*
* double x, y, atan();
*
* y = atan( x );
*
*
*
* DESCRIPTION:
*
* Returns radian angle between -pi/2 and +pi/2 whose tangent
* is x.
*
* Range reduction is from three intervals into the interval
* from zero to 0.66. The approximant uses a rational
* function of degree 4/5 of the form x + x**3 P(x)/Q(x).
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC -10, 10 50000 2.4e-17 8.3e-18
* IEEE -10, 10 10^6 1.8e-16 5.0e-17
*
*/
/* atan2()
*
* Quadrant correct inverse circular tangent
*
*
*
* SYNOPSIS:
*
* double x, y, z, atan2();
*
* z = atan2( y, x );
*
*
*
* DESCRIPTION:
*
* Returns radian angle whose tangent is y/x.
* Define compile time symbol ANSIC = 1 for ANSI standard,
* range -PI < z <= +PI, args (y,x); else ANSIC = 0 for range
* 0 to 2PI, args (x,y).
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* IEEE -10, 10 10^6 2.5e-16 6.9e-17
* See atan.c.
*
*/
/* atan.c */
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
/* arctan(x) = x + x^3 P(x^2)/Q(x^2)
0 <= x <= 0.66
Peak relative error = 2.6e-18 */
#ifdef UNK
const static double P[5] = {
-8.750608600031904122785E-1,
-1.615753718733365076637E1,
-7.500855792314704667340E1,
-1.228866684490136173410E2,
-6.485021904942025371773E1,
};
const static double Q[5] = {
/* 1.000000000000000000000E0, */
2.485846490142306297962E1,
1.650270098316988542046E2,
4.328810604912902668951E2,
4.853903996359136964868E2,
1.945506571482613964425E2,
};
/* tan( 3*pi/8 ) */
const static double T3P8 = 2.41421356237309504880;
#endif
#ifdef DEC
static short P[20] = {
0140140,0001775,0007671,0026242,
0141201,0041242,0155534,0001715,
0141626,0002141,0132100,0011625,
0141765,0142771,0064055,0150453,
0141601,0131517,0164507,0062164,
};
static short Q[20] = {
/* 0040200,0000000,0000000,0000000, */
0041306,0157042,0154243,0000742,
0042045,0003352,0016707,0150452,
0042330,0070306,0113425,0170730,
0042362,0130770,0116602,0047520,
0042102,0106367,0156753,0013541,
};
/* tan( 3*pi/8 ) = 2.41421356237309504880 */
static unsigned short T3P8A[] = {040432,0101171,0114774,0167462,};
#define T3P8 *(double *)T3P8A
#endif
#ifdef IBMPC
static short P[20] = {
0x2594,0xa1f7,0x007f,0xbfec,
0x807a,0x5b6b,0x2854,0xc030,
0x0273,0x3688,0xc08c,0xc052,
0xba25,0x2d05,0xb8bf,0xc05e,
0xec8e,0xfd28,0x3669,0xc050,
};
static short Q[20] = {
/* 0x0000,0x0000,0x0000,0x3ff0, */
0x603c,0x5b14,0xdbc4,0x4038,
0xfa25,0x43b8,0xa0dd,0x4064,
0xbe3b,0xd2e2,0x0e18,0x407b,
0x49ea,0x13b0,0x563f,0x407e,
0x62ec,0xfbbd,0x519e,0x4068,
};
/* tan( 3*pi/8 ) = 2.41421356237309504880 */
static unsigned short T3P8A[] = {0x9de6,0x333f,0x504f,0x4003};
#define T3P8 *(double *)T3P8A
#endif
#ifdef MIEEE
static short P[20] = {
0xbfec,0x007f,0xa1f7,0x2594,
0xc030,0x2854,0x5b6b,0x807a,
0xc052,0xc08c,0x3688,0x0273,
0xc05e,0xb8bf,0x2d05,0xba25,
0xc050,0x3669,0xfd28,0xec8e,
};
static short Q[20] = {
/* 0x3ff0,0x0000,0x0000,0x0000, */
0x4038,0xdbc4,0x5b14,0x603c,
0x4064,0xa0dd,0x43b8,0xfa25,
0x407b,0x0e18,0xd2e2,0xbe3b,
0x407e,0x563f,0x13b0,0x49ea,
0x4068,0x519e,0xfbbd,0x62ec,
};
/* tan( 3*pi/8 ) = 2.41421356237309504880 */
static unsigned short T3P8A[] = {
0x4003,0x504f,0x333f,0x9de6
};
#define T3P8 *(double *)T3P8A
#endif
#ifdef ANSIPROT
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
extern double atan ( double );
extern double fabs ( double );
extern int signbit ( double );
extern int isnan ( double );
#else
double polevl(), p1evl(), atan(), fabs();
int signbit(), isnan();
#endif
extern double PI, PIO2, PIO4, INFINITY, NEGZERO, MAXNUM;
/* pi/2 = PIO2 + MOREBITS. */
#ifdef DEC
#define MOREBITS 5.721188726109831840122E-18
#else
#define MOREBITS 6.123233995736765886130E-17
#endif
double atan(x)
double x;
{
double y, z;
short sign, flag;
#ifdef MINUSZERO
if( x == 0.0 )
return(x);
#endif
#ifdef INFINITIES
if(x == INFINITY)
return(PIO2);
if(x == -INFINITY)
return(-PIO2);
#endif
/* make argument positive and save the sign */
sign = 1;
if( x < 0.0 )
{
sign = -1;
x = -x;
}
/* range reduction */
flag = 0;
if( x > T3P8 )
{
y = PIO2;
flag = 1;
x = -( 1.0/x );
}
else if( x <= 0.66 )
{
y = 0.0;
}
else
{
y = PIO4;
flag = 2;
x = (x-1.0)/(x+1.0);
}
z = x * x;
z = z * polevl( z, P, 4 ) / p1evl( z, Q, 5 );
z = x * z + x;
if( flag == 2 )
z += 0.5 * MOREBITS;
else if( flag == 1 )
z += MOREBITS;
y = y + z;
if( sign < 0 )
y = -y;
return(y);
}
/* atan2 */
#ifdef ANSIC
double atan2( y, x )
#else
double atan2( x, y )
#endif
double x, y;
{
double z, w;
short code;
code = 0;
#ifdef NANS
if( isnan(x) )
return(x);
if( isnan(y) )
return(y);
#endif
#ifdef MINUSZERO
if( y == 0.0 )
{
if( signbit(y) )
{
if( x > 0.0 )
z = y;
else if( x < 0.0 )
z = -PI;
else
{
if( signbit(x) )
z = -PI;
else
z = y;
}
}
else /* y is +0 */
{
if( x == 0.0 )
{
if( signbit(x) )
z = PI;
else
z = 0.0;
}
else if( x > 0.0 )
z = 0.0;
else
z = PI;
}
return z;
}
if( x == 0.0 )
{
if( y > 0.0 )
z = PIO2;
else
z = -PIO2;
return z;
}
#endif /* MINUSZERO */
#ifdef INFINITIES
if( x == INFINITY )
{
if( y == INFINITY )
z = 0.25 * PI;
else if( y == -INFINITY )
z = -0.25 * PI;
else if( y < 0.0 )
z = NEGZERO;
else
z = 0.0;
return z;
}
if( x == -INFINITY )
{
if( y == INFINITY )
z = 0.75 * PI;
else if( y <= -INFINITY )
z = -0.75 * PI;
else if( y >= 0.0 )
z = PI;
else
z = -PI;
return z;
}
if( y == INFINITY )
return( PIO2 );
if( y == -INFINITY )
return( -PIO2 );
#endif
if( x < 0.0 )
code = 2;
if( y < 0.0 )
code |= 1;
#ifdef INFINITIES
if( x == 0.0 )
#else
if( fabs(x) <= (fabs(y) / MAXNUM) )
#endif
{
if( code & 1 )
{
#if ANSIC
return( -PIO2 );
#else
return( 3.0*PIO2 );
#endif
}
if( y == 0.0 )
return( 0.0 );
return( PIO2 );
}
if( y == 0.0 )
{
if( code & 2 )
return( PI );
return( 0.0 );
}
switch( code )
{
#if ANSIC
default:
case 0:
case 1: w = 0.0; break;
case 2: w = PI; break;
case 3: w = -PI; break;
#else
default:
case 0: w = 0.0; break;
case 1: w = 2.0 * PI; break;
case 2:
case 3: w = PI; break;
#endif
}
z = w + atan( y/x );
#ifdef MINUSZERO
if( z == 0.0 && y < 0 )
z = NEGZERO;
#endif
return( z );
}

View File

@@ -0,0 +1,156 @@
/* atanh.c
*
* Inverse hyperbolic tangent
*
*
*
* SYNOPSIS:
*
* double x, y, atanh();
*
* y = atanh( x );
*
*
*
* DESCRIPTION:
*
* Returns inverse hyperbolic tangent of argument in the range
* MINLOG to MAXLOG.
*
* If |x| < 0.5, the rational form x + x**3 P(x)/Q(x) is
* employed. Otherwise,
* atanh(x) = 0.5 * log( (1+x)/(1-x) ).
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC -1,1 50000 2.4e-17 6.4e-18
* IEEE -1,1 30000 1.9e-16 5.2e-17
*
*/
/* atanh.c */
/*
Cephes Math Library Release 2.8: June, 2000
Copyright (C) 1987, 1995, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
#ifdef UNK
const static double P[] = {
-8.54074331929669305196E-1,
1.20426861384072379242E1,
-4.61252884198732692637E1,
6.54566728676544377376E1,
-3.09092539379866942570E1
};
const static double Q[] = {
/* 1.00000000000000000000E0,*/
-1.95638849376911654834E1,
1.08938092147140262656E2,
-2.49839401325893582852E2,
2.52006675691344555838E2,
-9.27277618139601130017E1
};
#endif
#ifdef DEC
static unsigned short P[] = {
0140132,0122235,0105775,0130300,
0041100,0127327,0124407,0034722,
0141470,0100113,0115607,0130535,
0041602,0164721,0003257,0013673,
0141367,0043046,0166673,0045750
};
static unsigned short Q[] = {
/*0040200,0000000,0000000,0000000,*/
0141234,0101326,0015460,0134564,
0041731,0160115,0116451,0032045,
0142171,0153343,0000532,0167226,
0042174,0000665,0077604,0000310,
0141671,0072235,0031114,0074377
};
#endif
#ifdef IBMPC
static unsigned short P[] = {
0xb618,0xb17f,0x5493,0xbfeb,
0xe73a,0xf520,0x15da,0x4028,
0xf62c,0x7370,0x1009,0xc047,
0xe2f7,0x20d5,0x5d3a,0x4050,
0x697d,0xddb7,0xe8c4,0xc03e
};
static unsigned short Q[] = {
/*0x0000,0x0000,0x0000,0x3ff0,*/
0x172f,0xc366,0x905a,0xc033,
0x2685,0xb3a5,0x3c09,0x405b,
0x5dd3,0x602b,0x3adc,0xc06f,
0x8019,0xaff0,0x8036,0x406f,
0x8f20,0xa649,0x2e93,0xc057
};
#endif
#ifdef MIEEE
static unsigned short P[] = {
0xbfeb,0x5493,0xb17f,0xb618,
0x4028,0x15da,0xf520,0xe73a,
0xc047,0x1009,0x7370,0xf62c,
0x4050,0x5d3a,0x20d5,0xe2f7,
0xc03e,0xe8c4,0xddb7,0x697d
};
static unsigned short Q[] = {
0xc033,0x905a,0xc366,0x172f,
0x405b,0x3c09,0xb3a5,0x2685,
0xc06f,0x3adc,0x602b,0x5dd3,
0x406f,0x8036,0xaff0,0x8019,
0xc057,0x2e93,0xa649,0x8f20
};
#endif
#ifdef ANSIPROT
extern double fabs ( double );
extern double log ( double x );
extern double polevl ( double x, void *P, int N );
extern double p1evl ( double x, void *P, int N );
#else
double fabs(), log(), polevl(), p1evl();
#endif
extern double INFINITY, NAN;
double atanh(x)
double x;
{
double s, z;
#ifdef MINUSZERO
if( x == 0.0 )
return(x);
#endif
z = fabs(x);
if( z >= 1.0 )
{
if( x == 1.0 )
return( INFINITY );
if( x == -1.0 )
return( -INFINITY );
mtherr( "atanh", DOMAIN );
return( NAN );
}
if( z < 1.0e-7 )
return(x);
if( z < 0.5 )
{
z = x * x;
s = x + x * z * (polevl(z, P, 4) / p1evl(z, Q, 5));
return(s);
}
return( 0.5 * log((1.0+x)/(1.0-x)) );
}

View File

@@ -0,0 +1,142 @@
/* cbrt.c
*
* Cube root
*
*
*
* SYNOPSIS:
*
* double x, y, cbrt();
*
* y = cbrt( x );
*
*
*
* DESCRIPTION:
*
* Returns the cube root of the argument, which may be negative.
*
* Range reduction involves determining the power of 2 of
* the argument. A polynomial of degree 2 applied to the
* mantissa, and multiplication by the cube root of 1, 2, or 4
* approximates the root to within about 0.1%. Then Newton's
* iteration is used three times to converge to an accurate
* result.
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC -10,10 200000 1.8e-17 6.2e-18
* IEEE 0,1e308 30000 1.5e-16 5.0e-17
*
*/
/* cbrt.c */
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1991, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
const static double CBRT2 = 1.2599210498948731647672;
const static double CBRT4 = 1.5874010519681994747517;
const static double CBRT2I = 0.79370052598409973737585;
const static double CBRT4I = 0.62996052494743658238361;
#ifdef ANSIPROT
extern double frexp ( double, int * );
extern double ldexp ( double, int );
extern int isnan ( double );
extern int isfinite ( double );
#else
double frexp(), ldexp();
int isnan(), isfinite();
#endif
double cbrt(x)
double x;
{
int e, rem, sign;
double z;
#ifdef NANS
if( isnan(x) )
return x;
#endif
#ifdef INFINITIES
if( !isfinite(x) )
return x;
#endif
if( x == 0 )
return( x );
if( x > 0 )
sign = 1;
else
{
sign = -1;
x = -x;
}
z = x;
/* extract power of 2, leaving
* mantissa between 0.5 and 1
*/
x = frexp( x, &e );
/* Approximate cube root of number between .5 and 1,
* peak relative error = 9.2e-6
*/
x = (((-1.3466110473359520655053e-1 * x
+ 5.4664601366395524503440e-1) * x
- 9.5438224771509446525043e-1) * x
+ 1.1399983354717293273738e0 ) * x
+ 4.0238979564544752126924e-1;
/* exponent divided by 3 */
if( e >= 0 )
{
rem = e;
e /= 3;
rem -= 3*e;
if( rem == 1 )
x *= CBRT2;
else if( rem == 2 )
x *= CBRT4;
}
/* argument less than 1 */
else
{
e = -e;
rem = e;
e /= 3;
rem -= 3*e;
if( rem == 1 )
x *= CBRT2I;
else if( rem == 2 )
x *= CBRT4I;
e = -e;
}
/* multiply by power of 2 */
x = ldexp( x, e );
/* Newton iteration */
x -= ( x - (z/(x*x)) )*0.33333333333333333333;
#ifdef DEC
x -= ( x - (z/(x*x)) )/3.0;
#else
x -= ( x - (z/(x*x)) )*0.33333333333333333333;
#endif
if( sign < 0 )
x = -x;
return(x);
}

View File

@@ -0,0 +1,82 @@
/* chbevl.c
*
* Evaluate Chebyshev series
*
*
*
* SYNOPSIS:
*
* int N;
* double x, y, coef[N], chebevl();
*
* y = chbevl( x, coef, N );
*
*
*
* DESCRIPTION:
*
* Evaluates the series
*
* N-1
* - '
* y = > coef[i] T (x/2)
* - i
* i=0
*
* of Chebyshev polynomials Ti at argument x/2.
*
* Coefficients are stored in reverse order, i.e. the zero
* order term is last in the array. Note N is the number of
* coefficients, not the order.
*
* If coefficients are for the interval a to b, x must
* have been transformed to x -> 2(2x - b - a)/(b-a) before
* entering the routine. This maps x from (a, b) to (-1, 1),
* over which the Chebyshev polynomials are defined.
*
* If the coefficients are for the inverted interval, in
* which (a, b) is mapped to (1/b, 1/a), the transformation
* required is x -> 2(2ab/x - b - a)/(b-a). If b is infinity,
* this becomes x -> 4a/x - 1.
*
*
*
* SPEED:
*
* Taking advantage of the recurrence properties of the
* Chebyshev polynomials, the routine requires one more
* addition per loop than evaluating a nested polynomial of
* the same degree.
*
*/
/* chbevl.c */
/*
Cephes Math Library Release 2.0: April, 1987
Copyright 1985, 1987 by Stephen L. Moshier
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
*/
double chbevl( x, array, n )
double x;
double array[];
int n;
{
double b0, b1, b2, *p;
int i;
p = array;
b0 = *p++;
b1 = 0.0;
i = n - 1;
do
{
b2 = b1;
b1 = b0;
b0 = x * b1 - b2 + *p++;
}
while( --i );
return( 0.5*(b0-b2) );
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,461 @@
/* cmplx.c
*
* Complex number arithmetic
*
*
*
* SYNOPSIS:
*
* typedef struct {
* double r; real part
* double i; imaginary part
* }cmplx;
*
* cmplx *a, *b, *c;
*
* cadd( a, b, c ); c = b + a
* csub( a, b, c ); c = b - a
* cmul( a, b, c ); c = b * a
* cdiv( a, b, c ); c = b / a
* cneg( c ); c = -c
* cmov( b, c ); c = b
*
*
*
* DESCRIPTION:
*
* Addition:
* c.r = b.r + a.r
* c.i = b.i + a.i
*
* Subtraction:
* c.r = b.r - a.r
* c.i = b.i - a.i
*
* Multiplication:
* c.r = b.r * a.r - b.i * a.i
* c.i = b.r * a.i + b.i * a.r
*
* Division:
* d = a.r * a.r + a.i * a.i
* c.r = (b.r * a.r + b.i * a.i)/d
* c.i = (b.i * a.r - b.r * a.i)/d
* ACCURACY:
*
* In DEC arithmetic, the test (1/z) * z = 1 had peak relative
* error 3.1e-17, rms 1.2e-17. The test (y/z) * (z/y) = 1 had
* peak relative error 8.3e-17, rms 2.1e-17.
*
* Tests in the rectangle {-10,+10}:
* Relative error:
* arithmetic function # trials peak rms
* DEC cadd 10000 1.4e-17 3.4e-18
* IEEE cadd 100000 1.1e-16 2.7e-17
* DEC csub 10000 1.4e-17 4.5e-18
* IEEE csub 100000 1.1e-16 3.4e-17
* DEC cmul 3000 2.3e-17 8.7e-18
* IEEE cmul 100000 2.1e-16 6.9e-17
* DEC cdiv 18000 4.9e-17 1.3e-17
* IEEE cdiv 100000 3.7e-16 1.1e-16
*/
/* cmplx.c
* complex number arithmetic
*/
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
#ifdef ANSIPROT
extern double fabs ( double );
extern double cabs ( cmplx * );
extern double sqrt ( double );
extern double atan2 ( double, double );
extern double cos ( double );
extern double sin ( double );
extern double sqrt ( double );
extern double frexp ( double, int * );
extern double ldexp ( double, int );
int isnan ( double );
void cdiv ( cmplx *, cmplx *, cmplx * );
void cadd ( cmplx *, cmplx *, cmplx * );
#else
double fabs(), cabs(), sqrt(), atan2(), cos(), sin();
double sqrt(), frexp(), ldexp();
int isnan();
void cdiv(), cadd();
#endif
extern double MAXNUM, MACHEP, PI, PIO2, INFINITY, NAN;
/*
typedef struct
{
double r;
double i;
}cmplx;
*/
cmplx czero = {0.0, 0.0};
extern cmplx czero;
cmplx cone = {1.0, 0.0};
extern cmplx cone;
/* c = b + a */
void cadd( a, b, c )
register cmplx *a, *b;
cmplx *c;
{
c->r = b->r + a->r;
c->i = b->i + a->i;
}
/* c = b - a */
void csub( a, b, c )
register cmplx *a, *b;
cmplx *c;
{
c->r = b->r - a->r;
c->i = b->i - a->i;
}
/* c = b * a */
void cmul( a, b, c )
register cmplx *a, *b;
cmplx *c;
{
double y;
y = b->r * a->r - b->i * a->i;
c->i = b->r * a->i + b->i * a->r;
c->r = y;
}
/* c = b / a */
void cdiv( a, b, c )
register cmplx *a, *b;
cmplx *c;
{
double y, p, q, w;
y = a->r * a->r + a->i * a->i;
p = b->r * a->r + b->i * a->i;
q = b->i * a->r - b->r * a->i;
if( y < 1.0 )
{
w = MAXNUM * y;
if( (fabs(p) > w) || (fabs(q) > w) || (y == 0.0) )
{
c->r = MAXNUM;
c->i = MAXNUM;
mtherr( "cdiv", OVERFLOW );
return;
}
}
c->r = p/y;
c->i = q/y;
}
/* b = a
Caution, a `short' is assumed to be 16 bits wide. */
void cmov( a, b )
void *a, *b;
{
register short *pa, *pb;
int i;
pa = (short *) a;
pb = (short *) b;
i = 8;
do
*pb++ = *pa++;
while( --i );
}
void cneg( a )
register cmplx *a;
{
a->r = -a->r;
a->i = -a->i;
}
/* cabs()
*
* Complex absolute value
*
*
*
* SYNOPSIS:
*
* double cabs();
* cmplx z;
* double a;
*
* a = cabs( &z );
*
*
*
* DESCRIPTION:
*
*
* If z = x + iy
*
* then
*
* a = sqrt( x**2 + y**2 ).
*
* Overflow and underflow are avoided by testing the magnitudes
* of x and y before squaring. If either is outside half of
* the floating point full scale range, both are rescaled.
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC -30,+30 30000 3.2e-17 9.2e-18
* IEEE -10,+10 100000 2.7e-16 6.9e-17
*/
/*
Cephes Math Library Release 2.1: January, 1989
Copyright 1984, 1987, 1989 by Stephen L. Moshier
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
*/
/*
typedef struct
{
double r;
double i;
}cmplx;
*/
#ifdef UNK
#define PREC 27
#define MAXEXP 1024
#define MINEXP -1077
#endif
#ifdef DEC
#define PREC 29
#define MAXEXP 128
#define MINEXP -128
#endif
#ifdef IBMPC
#define PREC 27
#define MAXEXP 1024
#define MINEXP -1077
#endif
#ifdef MIEEE
#define PREC 27
#define MAXEXP 1024
#define MINEXP -1077
#endif
double cabs( z )
register cmplx *z;
{
double x, y, b, re, im;
int ex, ey, e;
#ifdef INFINITIES
/* Note, cabs(INFINITY,NAN) = INFINITY. */
if( z->r == INFINITY || z->i == INFINITY
|| z->r == -INFINITY || z->i == -INFINITY )
return( INFINITY );
#endif
#ifdef NANS
if( isnan(z->r) )
return(z->r);
if( isnan(z->i) )
return(z->i);
#endif
re = fabs( z->r );
im = fabs( z->i );
if( re == 0.0 )
return( im );
if( im == 0.0 )
return( re );
/* Get the exponents of the numbers */
x = frexp( re, &ex );
y = frexp( im, &ey );
/* Check if one number is tiny compared to the other */
e = ex - ey;
if( e > PREC )
return( re );
if( e < -PREC )
return( im );
/* Find approximate exponent e of the geometric mean. */
e = (ex + ey) >> 1;
/* Rescale so mean is about 1 */
x = ldexp( re, -e );
y = ldexp( im, -e );
/* Hypotenuse of the right triangle */
b = sqrt( x * x + y * y );
/* Compute the exponent of the answer. */
y = frexp( b, &ey );
ey = e + ey;
/* Check it for overflow and underflow. */
if( ey > MAXEXP )
{
mtherr( "cabs", OVERFLOW );
return( INFINITY );
}
if( ey < MINEXP )
return(0.0);
/* Undo the scaling */
b = ldexp( b, e );
return( b );
}
/* csqrt()
*
* Complex square root
*
*
*
* SYNOPSIS:
*
* void csqrt();
* cmplx z, w;
*
* csqrt( &z, &w );
*
*
*
* DESCRIPTION:
*
*
* If z = x + iy, r = |z|, then
*
* 1/2
* Im w = [ (r - x)/2 ] ,
*
* Re w = y / 2 Im w.
*
*
* Note that -w is also a square root of z. The root chosen
* is always in the upper half plane.
*
* Because of the potential for cancellation error in r - x,
* the result is sharpened by doing a Heron iteration
* (see sqrt.c) in complex arithmetic.
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC -10,+10 25000 3.2e-17 9.6e-18
* IEEE -10,+10 100000 3.2e-16 7.7e-17
*
* 2
* Also tested by csqrt( z ) = z, and tested by arguments
* close to the real axis.
*/
void csqrt( z, w )
cmplx *z, *w;
{
cmplx q, s;
double x, y, r, t;
x = z->r;
y = z->i;
if( y == 0.0 )
{
if( x < 0.0 )
{
w->r = 0.0;
w->i = sqrt(-x);
return;
}
else
{
w->r = sqrt(x);
w->i = 0.0;
return;
}
}
if( x == 0.0 )
{
r = fabs(y);
r = sqrt(0.5*r);
if( y > 0 )
w->r = r;
else
w->r = -r;
w->i = r;
return;
}
/* Approximate sqrt(x^2+y^2) - x = y^2/2x - y^4/24x^3 + ... .
* The relative error in the first term is approximately y^2/12x^2 .
*/
if( (fabs(y) < 2.e-4 * fabs(x))
&& (x > 0) )
{
t = 0.25*y*(y/x);
}
else
{
r = cabs(z);
t = 0.5*(r - x);
}
r = sqrt(t);
q.i = r;
q.r = y/(2.0*r);
/* Heron iteration in complex arithmetic */
cdiv( &q, z, &s );
cadd( &q, &s, w );
w->r *= 0.5;
w->i *= 0.5;
}
double hypot( x, y )
double x, y;
{
cmplx z;
z.r = x;
z.i = y;
return( cabs(&z) );
}

View File

@@ -0,0 +1,252 @@
/* const.c
*
* Globally declared constants
*
*
*
* SYNOPSIS:
*
* extern const double nameofconstant;
*
*
*
*
* DESCRIPTION:
*
* This file contains a number of mathematical constants and
* also some needed size parameters of the computer arithmetic.
* The values are supplied as arrays of hexadecimal integers
* for IEEE arithmetic; arrays of octal constants for DEC
* arithmetic; and in a normal decimal scientific notation for
* other machines. The particular notation used is determined
* by a symbol (DEC, IBMPC, or UNK) defined in the include file
* mconf.h.
*
* The default size parameters are as follows.
*
* For DEC and UNK modes:
* MACHEP = 1.38777878078144567553E-17 2**-56
* MAXLOG = 8.8029691931113054295988E1 log(2**127)
* MINLOG = -8.872283911167299960540E1 log(2**-128)
* MAXNUM = 1.701411834604692317316873e38 2**127
*
* For IEEE arithmetic (IBMPC):
* MACHEP = 1.11022302462515654042E-16 2**-53
* MAXLOG = 7.09782712893383996843E2 log(2**1024)
* MINLOG = -7.08396418532264106224E2 log(2**-1022)
* MAXNUM = 1.7976931348623158E308 2**1024
*
* The global symbols for mathematical constants are
* PI = 3.14159265358979323846 pi
* PIO2 = 1.57079632679489661923 pi/2
* PIO4 = 7.85398163397448309616E-1 pi/4
* SQRT2 = 1.41421356237309504880 sqrt(2)
* SQRTH = 7.07106781186547524401E-1 sqrt(2)/2
* LOG2E = 1.4426950408889634073599 1/log(2)
* SQ2OPI = 7.9788456080286535587989E-1 sqrt( 2/pi )
* LOGE2 = 6.93147180559945309417E-1 log(2)
* LOGSQ2 = 3.46573590279972654709E-1 log(2)/2
* THPIO4 = 2.35619449019234492885 3*pi/4
* TWOOPI = 6.36619772367581343075535E-1 2/pi
*
* These lists are subject to change.
*/
/* const.c */
/*
Cephes Math Library Release 2.3: March, 1995
Copyright 1984, 1995 by Stephen L. Moshier
*/
#include "mconf.h"
#ifdef UNK
#if 1
const double MACHEP = 1.11022302462515654042E-16; /* 2**-53 */
#else
const double MACHEP = 1.38777878078144567553E-17; /* 2**-56 */
#endif
const double UFLOWTHRESH = 2.22507385850720138309E-308; /* 2**-1022 */
#ifdef DENORMAL
const double MAXLOG = 7.09782712893383996732E2; /* log(MAXNUM) */
/* const double MINLOG = -7.44440071921381262314E2; */ /* log(2**-1074) */
const double MINLOG = -7.451332191019412076235E2; /* log(2**-1075) */
#else
const double MAXLOG = 7.08396418532264106224E2; /* log 2**1022 */
const double MINLOG = -7.08396418532264106224E2; /* log 2**-1022 */
#endif
const double MAXNUM = 1.79769313486231570815E308; /* 2**1024*(1-MACHEP) */
const double PI = 3.14159265358979323846; /* pi */
const double PIO2 = 1.57079632679489661923; /* pi/2 */
const double PIO4 = 7.85398163397448309616E-1; /* pi/4 */
const double SQRT2 = 1.41421356237309504880; /* sqrt(2) */
const double SQRTH = 7.07106781186547524401E-1; /* sqrt(2)/2 */
const double LOG2E = 1.4426950408889634073599; /* 1/log(2) */
const double SQ2OPI = 7.9788456080286535587989E-1; /* sqrt( 2/pi ) */
const double LOGE2 = 6.93147180559945309417E-1; /* log(2) */
const double LOGSQ2 = 3.46573590279972654709E-1; /* log(2)/2 */
const double THPIO4 = 2.35619449019234492885; /* 3*pi/4 */
const double TWOOPI = 6.36619772367581343075535E-1; /* 2/pi */
#ifdef INFINITIES
const double INFINITY = 1.0/0.0; /* 99e999; */
#else
const double INFINITY = 1.79769313486231570815E308; /* 2**1024*(1-MACHEP) */
#endif
#ifdef NANS
const double NAN = 1.0/0.0 - 1.0/0.0;
#else
const double NAN = 0.0;
#endif
#ifdef MINUSZERO
const double NEGZERO = -0.0;
#else
const double NEGZERO = 0.0;
#endif
#endif
#ifdef IBMPC
/* 2**-53 = 1.11022302462515654042E-16 */
const unsigned short MACHEP[4] = {0x0000,0x0000,0x0000,0x3ca0};
const unsigned short UFLOWTHRESH[4] = {0x0000,0x0000,0x0000,0x0010};
#ifdef DENORMAL
/* log(MAXNUM) = 7.09782712893383996732224E2 */
const unsigned short MAXLOG[4] = {0x39ef,0xfefa,0x2e42,0x4086};
/* log(2**-1074) = - -7.44440071921381262314E2 */
/*const unsigned short MINLOG[4] = {0x71c3,0x446d,0x4385,0xc087};*/
const unsigned short MINLOG[4] = {0x3052,0xd52d,0x4910,0xc087};
#else
/* log(2**1022) = 7.08396418532264106224E2 */
const unsigned short MAXLOG[4] = {0xbcd2,0xdd7a,0x232b,0x4086};
/* log(2**-1022) = - 7.08396418532264106224E2 */
const unsigned short MINLOG[4] = {0xbcd2,0xdd7a,0x232b,0xc086};
#endif
/* 2**1024*(1-MACHEP) = 1.7976931348623158E308 */
const unsigned short MAXNUM[4] = {0xffff,0xffff,0xffff,0x7fef};
const unsigned short PI[4] = {0x2d18,0x5444,0x21fb,0x4009};
const unsigned short PIO2[4] = {0x2d18,0x5444,0x21fb,0x3ff9};
const unsigned short PIO4[4] = {0x2d18,0x5444,0x21fb,0x3fe9};
const unsigned short SQRT2[4] = {0x3bcd,0x667f,0xa09e,0x3ff6};
const unsigned short SQRTH[4] = {0x3bcd,0x667f,0xa09e,0x3fe6};
const unsigned short LOG2E[4] = {0x82fe,0x652b,0x1547,0x3ff7};
const unsigned short SQ2OPI[4] = {0x3651,0x33d4,0x8845,0x3fe9};
const unsigned short LOGE2[4] = {0x39ef,0xfefa,0x2e42,0x3fe6};
const unsigned short LOGSQ2[4] = {0x39ef,0xfefa,0x2e42,0x3fd6};
const unsigned short THPIO4[4] = {0x21d2,0x7f33,0xd97c,0x4002};
const unsigned short TWOOPI[4] = {0xc883,0x6dc9,0x5f30,0x3fe4};
#ifdef INFINITIES
const unsigned short INFINITY[4] = {0x0000,0x0000,0x0000,0x7ff0};
#else
const unsigned short INFINITY[4] = {0xffff,0xffff,0xffff,0x7fef};
#endif
#ifdef NANS
const unsigned short NAN[4] = {0x0000,0x0000,0x0000,0x7ffc};
#else
const unsigned short NAN[4] = {0x0000,0x0000,0x0000,0x0000};
#endif
#ifdef MINUSZERO
const unsigned short NEGZERO[4] = {0x0000,0x0000,0x0000,0x8000};
#else
const unsigned short NEGZERO[4] = {0x0000,0x0000,0x0000,0x0000};
#endif
#endif
#ifdef MIEEE
/* 2**-53 = 1.11022302462515654042E-16 */
const unsigned short MACHEP[4] = {0x3ca0,0x0000,0x0000,0x0000};
const unsigned short UFLOWTHRESH[4] = {0x0010,0x0000,0x0000,0x0000};
#ifdef DENORMAL
/* log(2**1024) = 7.09782712893383996843E2 */
const unsigned short MAXLOG[4] = {0x4086,0x2e42,0xfefa,0x39ef};
/* log(2**-1074) = - -7.44440071921381262314E2 */
/* const unsigned short MINLOG[4] = {0xc087,0x4385,0x446d,0x71c3}; */
const unsigned short MINLOG[4] = {0xc087,0x4910,0xd52d,0x3052};
#else
/* log(2**1022) = 7.08396418532264106224E2 */
const unsigned short MAXLOG[4] = {0x4086,0x232b,0xdd7a,0xbcd2};
/* log(2**-1022) = - 7.08396418532264106224E2 */
const unsigned short MINLOG[4] = {0xc086,0x232b,0xdd7a,0xbcd2};
#endif
/* 2**1024*(1-MACHEP) = 1.7976931348623158E308 */
const unsigned short MAXNUM[4] = {0x7fef,0xffff,0xffff,0xffff};
const unsigned short PI[4] = {0x4009,0x21fb,0x5444,0x2d18};
const unsigned short PIO2[4] = {0x3ff9,0x21fb,0x5444,0x2d18};
const unsigned short PIO4[4] = {0x3fe9,0x21fb,0x5444,0x2d18};
const unsigned short SQRT2[4] = {0x3ff6,0xa09e,0x667f,0x3bcd};
const unsigned short SQRTH[4] = {0x3fe6,0xa09e,0x667f,0x3bcd};
const unsigned short LOG2E[4] = {0x3ff7,0x1547,0x652b,0x82fe};
const unsigned short SQ2OPI[4] = {0x3fe9,0x8845,0x33d4,0x3651};
const unsigned short LOGE2[4] = {0x3fe6,0x2e42,0xfefa,0x39ef};
const unsigned short LOGSQ2[4] = {0x3fd6,0x2e42,0xfefa,0x39ef};
const unsigned short THPIO4[4] = {0x4002,0xd97c,0x7f33,0x21d2};
const unsigned short TWOOPI[4] = {0x3fe4,0x5f30,0x6dc9,0xc883};
#ifdef INFINITIES
const unsigned short INFINITY[4] = {0x7ff0,0x0000,0x0000,0x0000};
#else
const unsigned short INFINITY[4] = {0x7fef,0xffff,0xffff,0xffff};
#endif
#ifdef NANS
const unsigned short NAN[4] = {0x7ff8,0x0000,0x0000,0x0000};
#else
const unsigned short NAN[4] = {0x0000,0x0000,0x0000,0x0000};
#endif
#ifdef MINUSZERO
const unsigned short NEGZERO[4] = {0x8000,0x0000,0x0000,0x0000};
#else
const unsigned short NEGZERO[4] = {0x0000,0x0000,0x0000,0x0000};
#endif
#endif
#ifdef DEC
/* 2**-56 = 1.38777878078144567553E-17 */
const unsigned short MACHEP[4] = {0022200,0000000,0000000,0000000};
const unsigned short UFLOWTHRESH[4] = {0x0080,0x0000,0x0000,0x0000};
/* log 2**127 = 88.029691931113054295988 */
const unsigned short MAXLOG[4] = {041660,007463,0143742,025733,};
/* log 2**-128 = -88.72283911167299960540 */
const unsigned short MINLOG[4] = {0141661,071027,0173721,0147572,};
/* 2**127 = 1.701411834604692317316873e38 */
const unsigned short MAXNUM[4] = {077777,0177777,0177777,0177777,};
const unsigned short PI[4] = {040511,007732,0121041,064302,};
const unsigned short PIO2[4] = {040311,007732,0121041,064302,};
const unsigned short PIO4[4] = {040111,007732,0121041,064302,};
const unsigned short SQRT2[4] = {040265,002363,031771,0157145,};
const unsigned short SQRTH[4] = {040065,002363,031771,0157144,};
const unsigned short LOG2E[4] = {040270,0125073,024534,013761,};
const unsigned short SQ2OPI[4] = {040114,041051,0117241,0131204,};
const unsigned short LOGE2[4] = {040061,071027,0173721,0147572,};
const unsigned short LOGSQ2[4] = {037661,071027,0173721,0147572,};
const unsigned short THPIO4[4] = {040426,0145743,0174631,007222,};
const unsigned short TWOOPI[4] = {040042,0174603,067116,042025,};
/* Approximate infinity by MAXNUM. */
const unsigned short INFINITY[4] = {077777,0177777,0177777,0177777,};
const unsigned short NAN[4] = {0000000,0000000,0000000,0000000};
#ifdef MINUSZERO
const unsigned short NEGZERO[4] = {0000000,0000000,0000000,0100000};
#else
const unsigned short NEGZERO[4] = {0000000,0000000,0000000,0000000};
#endif
#endif
#ifndef UNK
extern const unsigned short MACHEP[];
extern const unsigned short UFLOWTHRESH[];
extern const unsigned short MAXLOG[];
extern const unsigned short UNDLOG[];
extern const unsigned short MINLOG[];
extern const unsigned short MAXNUM[];
extern const unsigned short PI[];
extern const unsigned short PIO2[];
extern const unsigned short PIO4[];
extern const unsigned short SQRT2[];
extern const unsigned short SQRTH[];
extern const unsigned short LOG2E[];
extern const unsigned short SQ2OPI[];
extern const unsigned short LOGE2[];
extern const unsigned short LOGSQ2[];
extern const unsigned short THPIO4[];
extern const unsigned short TWOOPI[];
extern const unsigned short INFINITY[];
extern const unsigned short NAN[];
extern const unsigned short NEGZERO[];
#endif

View File

@@ -0,0 +1,83 @@
/* cosh.c
*
* Hyperbolic cosine
*
*
*
* SYNOPSIS:
*
* double x, y, cosh();
*
* y = cosh( x );
*
*
*
* DESCRIPTION:
*
* Returns hyperbolic cosine of argument in the range MINLOG to
* MAXLOG.
*
* cosh(x) = ( exp(x) + exp(-x) )/2.
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC +- 88 50000 4.0e-17 7.7e-18
* IEEE +-MAXLOG 30000 2.6e-16 5.7e-17
*
*
* ERROR MESSAGES:
*
* message condition value returned
* cosh overflow |x| > MAXLOG MAXNUM
*
*
*/
/* cosh.c */
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1985, 1995, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
#ifdef ANSIPROT
extern double exp ( double );
extern int isnan ( double );
extern int isfinite ( double );
#else
double exp();
int isnan(), isfinite();
#endif
extern double MAXLOG, INFINITY, LOGE2;
double cosh(x)
double x;
{
double y;
#ifdef NANS
if( isnan(x) )
return(x);
#endif
if( x < 0 )
x = -x;
if( x > (MAXLOG + LOGE2) )
{
mtherr( "cosh", OVERFLOW );
return( INFINITY );
}
if( x >= (MAXLOG - LOGE2) )
{
y = exp(0.5 * x);
y = (0.5 * y) * y;
return(y);
}
y = exp(x);
y = 0.5 * (y + 1.0 / y);
return( y );
}

View File

@@ -0,0 +1,99 @@
CFLAGS= /DEBUG/NOLIST
hfiles= mconf.h-
ofiles= acosh.obj-
asin.obj-
asinh.obj-
atan.obj-
atanh.obj-
cbrt.obj-
chbevl.obj-
const.obj-
cosh.obj-
drand.obj-
exp.obj-
exp10.obj-
fabs.obj-
floor.obj-
log.obj-
log10.obj-
polevl.obj-
pow.obj-
powi.obj-
round.obj-
sin.obj-
sinh.obj-
tan.obj-
tanh.obj-
unity.obj-
sqrt.obj-
floor.obj-
polevl.obj-
mtherr.obj
mtst.exe : $(ofiles)
LINK mtst/option
acosh.obj : acosh.c,$(HFILES)
CC $(CFLAGS) acosh
asin.obj : asin.c,$(HFILES)
CC $(CFLAGS) asin
asinh.obj : asinh.c,$(HFILES)
CC $(CFLAGS) asinh
atan.obj : atan.c,$(HFILES)
CC $(CFLAGS) atan
atan.obj : atan.c,$(HFILES)
CC $(CFLAGS) atan
atanh.obj : atanh.c,$(HFILES)
CC $(CFLAGS) atanh
cbrt.obj : cbrt.c,$(HFILES)
CC $(CFLAGS) cbrt
chbevl.obj : chbevl.c,$(HFILES)
CC $(CFLAGS) chbevl
const.obj : const.c,$(HFILES)
CC $(CFLAGS) const
cosh.obj : cosh.c,$(HFILES)
CC $(CFLAGS) cosh
drand.obj : drand.c,$(HFILES)
CC $(CFLAGS) drand
exp.obj : exp.c,$(HFILES)
CC $(CFLAGS) exp
exp10.obj : exp10.c,$(HFILES)
CC $(CFLAGS) exp10
fabs.obj : fabs.c,$(HFILES)
CC $(CFLAGS) fabs
floor.obj : floor.c,$(HFILES)
CC $(CFLAGS) floor
log.obj : log.c,$(HFILES)
CC $(CFLAGS) log
log10.obj : log10.c,$(HFILES)
CC $(CFLAGS) log10
polevl.obj : polevl.c,$(HFILES)
CC $(CFLAGS) polevl
pow.obj : pow.c,$(HFILES)
CC $(CFLAGS) pow
powi.obj : powi.c,$(HFILES)
CC $(CFLAGS) powi
round.obj : round.c,$(HFILES)
CC $(CFLAGS) round
sin.obj : sin.c,$(HFILES)
CC $(CFLAGS) sin
sinh.obj : sinh.c,$(HFILES)
CC $(CFLAGS) sinh
tan.obj : tan.c,$(HFILES)
CC $(CFLAGS) tan
tanh.obj : tanh.c,$(HFILES)
CC $(CFLAGS) tanh
unity.obj : unity.c,$(HFILES)
CC $(CFLAGS) unity
sqrt.obj : sqrt.c,$(HFILES)
CC $(CFLAGS) sqrt
mtherr.obj : mtherr.c,$(HFILES)
CC $(CFLAGS) mtherr

View File

@@ -0,0 +1,161 @@
/* drand.c
*
* Pseudorandom number generator
*
*
*
* SYNOPSIS:
*
* double y, drand();
*
* drand( &y );
*
*
*
* DESCRIPTION:
*
* Yields a random number 1.0 <= y < 2.0.
*
* The three-generator congruential algorithm by Brian
* Wichmann and David Hill (BYTE magazine, March, 1987,
* pp 127-8) is used. The period, given by them, is
* 6953607871644.
*
* Versions invoked by the different arithmetic compile
* time options DEC, IBMPC, and MIEEE, produce
* approximately the same sequences, differing only in the
* least significant bits of the numbers. The UNK option
* implements the algorithm as recommended in the BYTE
* article. It may be used on all computers. However,
* the low order bits of a double precision number may
* not be adequately random, and may vary due to arithmetic
* implementation details on different computers.
*
* The other compile options generate an additional random
* integer that overwrites the low order bits of the double
* precision number. This reduces the period by a factor of
* two but tends to overcome the problems mentioned.
*
*/
/* Three-generator random number algorithm
* of Brian Wichmann and David Hill
* BYTE magazine, March, 1987 pp 127-8
*
* The period, given by them, is (p-1)(q-1)(r-1)/4 = 6.95e12.
*/
#include "mconf.h"
#ifdef ANSIPROT
static int ranwh ( void );
#else
static int ranwh();
#endif
static int sx = 1;
static int sy = 10000;
static int sz = 3000;
static union {
double d;
unsigned short s[4];
} unkans;
/* This function implements the three
* congruential generators.
*/
static int ranwh()
{
int r, s;
/* sx = sx * 171 mod 30269 */
r = sx/177;
s = sx - 177 * r;
sx = 171 * s - 2 * r;
if( sx < 0 )
sx += 30269;
/* sy = sy * 172 mod 30307 */
r = sy/176;
s = sy - 176 * r;
sy = 172 * s - 35 * r;
if( sy < 0 )
sy += 30307;
/* sz = 170 * sz mod 30323 */
r = sz/178;
s = sz - 178 * r;
sz = 170 * s - 63 * r;
if( sz < 0 )
sz += 30323;
/* The results are in static sx, sy, sz. */
return 0;
}
/* drand.c
*
* Random double precision floating point number between 1 and 2.
*
* C callable:
* drand( &x );
*/
int drand( a )
double *a;
{
unsigned short r;
#ifdef DEC
unsigned short s, t;
#endif
/* This algorithm of Wichmann and Hill computes a floating point
* result:
*/
ranwh();
unkans.d = sx/30269.0 + sy/30307.0 + sz/30323.0;
r = unkans.d;
unkans.d -= r;
unkans.d += 1.0;
/* if UNK option, do nothing further.
* Otherwise, make a random 16 bit integer
* to overwrite the least significant word
* of unkans.
*/
#ifdef UNK
/* do nothing */
#else
ranwh();
r = sx * sy + sz;
#endif
#ifdef DEC
/* To make the numbers as similar as possible
* in all arithmetics, the random integer has
* to be inserted 3 bits higher up in a DEC number.
* An alternative would be put it 3 bits lower down
* in all the other number types.
*/
s = unkans.s[2];
t = s & 07; /* save these bits to put in at the bottom */
s &= 0177770;
s |= (r >> 13) & 07;
unkans.s[2] = s;
t |= r << 3;
unkans.s[3] = t;
#endif
#ifdef IBMPC
unkans.s[0] = r;
#endif
#ifdef MIEEE
unkans.s[3] = r;
#endif
*a = unkans.d;
return 0;
}

View File

@@ -0,0 +1,543 @@
/* Test vectors for math functions.
See C9X section F.9. */
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1998, 2000 by Stephen L. Moshier
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int isfinite (double);
/* C9X spells lgam lgamma. */
#define GLIBC2 0
extern double PI;
const static double MPI, PIO2, MPIO2, PIO4, MPIO4, THPIO4, MTHPIO4;
#if 0
#define PI 3.141592653589793238463E0
#define PIO2 1.570796326794896619231E0
#define PIO4 7.853981633974483096157E-1
#define THPIO4 2.35619449019234492884698
#define SQRT2 1.414213562373095048802E0
#define SQRTH 7.071067811865475244008E-1
#define INF (1.0/0.0)
#define MINF (-1.0/0.0)
#endif
extern double MACHEP, SQRTH, SQRT2;
extern double NAN, INFINITY, NEGZERO;
const static double INF, MINF;
const static double ZERO, MZERO, HALF, MHALF, ONE, MONE, TWO, MTWO, THREE, MTHREE;
/* #define NAN (1.0/0.0 - 1.0/0.0) */
/* Functions of one variable. */
double log (double);
double exp ( double);
double atan (double);
double sin (double);
double cos (double);
double tan (double);
double acos (double);
double asin (double);
double acosh (double);
double asinh (double);
double atanh (double);
double sinh (double);
double cosh (double);
double tanh (double);
double exp2 (double);
double expm1 (double);
double log10 (double);
double log1p (double);
double log2 (double);
double fabs (double);
double erf (double);
double erfc (double);
double gamma (double);
double floor (double);
double ceil (double);
double cbrt (double);
#if GLIBC2
double lgamma (double);
#else
double lgam (double);
#endif
struct oneargument
{
char *name; /* Name of the function. */
double (*func) (double);
double *arg1;
double *answer;
int thresh; /* Error report threshold. */
};
struct oneargument test1[] =
{
{"atan", atan, &ONE, &PIO4, 0},
{"sin", sin, &PIO2, &ONE, 0},
#if 0
{"cos", cos, &PIO4, &SQRTH, 0},
{"sin", sin, 32767., 1.8750655394138942394239E-1, 0},
{"cos", cos, 32767., 9.8226335176928229845654E-1, 0},
{"tan", tan, 32767., 1.9089234430221485740826E-1, 0},
{"sin", sin, 8388607., 9.9234509376961249835628E-1, 0},
{"cos", cos, 8388607., -1.2349580912475928183718E-1, 0},
{"tan", tan, 8388607., -8.0354556223613614748329E0, 0},
/*
{"sin", sin, 2147483647., -7.2491655514455639054829E-1, 0},
{"cos", cos, 2147483647., -6.8883669187794383467976E-1, 0},
{"tan", tan, 2147483647., 1.0523779637351339136698E0, 0},
*/
{"cos", cos, &PIO2, 6.1232339957367574e-17, 1},
{"sin", sin, &PIO4, &SQRTH, 1},
#endif
{"acos", acos, &NAN, &NAN, 0},
{"acos", acos, &ONE, &ZERO, 0},
{"acos", acos, &TWO, &NAN, 0},
{"acos", acos, &MTWO, &NAN, 0},
{"asin", asin, &NAN, &NAN, 0},
{"asin", asin, &ZERO, &ZERO, 0},
{"asin", asin, &MZERO, &MZERO, 0},
{"asin", asin, &TWO, &NAN, 0},
{"asin", asin, &MTWO, &NAN, 0},
{"atan", atan, &NAN, &NAN, 0},
{"atan", atan, &ZERO, &ZERO, 0},
{"atan", atan, &MZERO, &MZERO, 0},
{"atan", atan, &INF, &PIO2, 0},
{"atan", atan, &MINF, &MPIO2, 0},
{"cos", cos, &NAN, &NAN, 0},
{"cos", cos, &ZERO, &ONE, 0},
{"cos", cos, &MZERO, &ONE, 0},
{"cos", cos, &INF, &NAN, 0},
{"cos", cos, &MINF, &NAN, 0},
{"sin", sin, &NAN, &NAN, 0},
{"sin", sin, &MZERO, &MZERO, 0},
{"sin", sin, &ZERO, &ZERO, 0},
{"sin", sin, &INF, &NAN, 0},
{"sin", sin, &MINF, &NAN, 0},
{"tan", tan, &NAN, &NAN, 0},
{"tan", tan, &ZERO, &ZERO, 0},
{"tan", tan, &MZERO, &MZERO, 0},
{"tan", tan, &INF, &NAN, 0},
{"tan", tan, &MINF, &NAN, 0},
{"acosh", acosh, &NAN, &NAN, 0},
{"acosh", acosh, &ONE, &ZERO, 0},
{"acosh", acosh, &INF, &INF, 0},
{"acosh", acosh, &HALF, &NAN, 0},
{"acosh", acosh, &MONE, &NAN, 0},
{"asinh", asinh, &NAN, &NAN, 0},
{"asinh", asinh, &ZERO, &ZERO, 0},
{"asinh", asinh, &MZERO, &MZERO, 0},
{"asinh", asinh, &INF, &INF, 0},
{"asinh", asinh, &MINF, &MINF, 0},
{"atanh", atanh, &NAN, &NAN, 0},
{"atanh", atanh, &ZERO, &ZERO, 0},
{"atanh", atanh, &MZERO, &MZERO, 0},
{"atanh", atanh, &ONE, &INF, 0},
{"atanh", atanh, &MONE, &MINF, 0},
{"atanh", atanh, &TWO, &NAN, 0},
{"atanh", atanh, &MTWO, &NAN, 0},
{"cosh", cosh, &NAN, &NAN, 0},
{"cosh", cosh, &ZERO, &ONE, 0},
{"cosh", cosh, &MZERO, &ONE, 0},
{"cosh", cosh, &INF, &INF, 0},
{"cosh", cosh, &MINF, &INF, 0},
{"sinh", sinh, &NAN, &NAN, 0},
{"sinh", sinh, &ZERO, &ZERO, 0},
{"sinh", sinh, &MZERO, &MZERO, 0},
{"sinh", sinh, &INF, &INF, 0},
{"sinh", sinh, &MINF, &MINF, 0},
{"tanh", tanh, &NAN, &NAN, 0},
{"tanh", tanh, &ZERO, &ZERO, 0},
{"tanh", tanh, &MZERO, &MZERO, 0},
{"tanh", tanh, &INF, &ONE, 0},
{"tanh", tanh, &MINF, &MONE, 0},
{"exp", exp, &NAN, &NAN, 0},
{"exp", exp, &ZERO, &ONE, 0},
{"exp", exp, &MZERO, &ONE, 0},
{"exp", exp, &INF, &INF, 0},
{"exp", exp, &MINF, &ZERO, 0},
#if !GLIBC2
{"exp2", exp2, &NAN, &NAN, 0},
{"exp2", exp2, &ZERO, &ONE, 0},
{"exp2", exp2, &MZERO, &ONE, 0},
{"exp2", exp2, &INF, &INF, 0},
{"exp2", exp2, &MINF, &ZERO, 0},
#endif
{"expm1", expm1, &NAN, &NAN, 0},
{"expm1", expm1, &ZERO, &ZERO, 0},
{"expm1", expm1, &MZERO, &MZERO, 0},
{"expm1", expm1, &INF, &INF, 0},
{"expm1", expm1, &MINF, &MONE, 0},
{"log", log, &NAN, &NAN, 0},
{"log", log, &ZERO, &MINF, 0},
{"log", log, &MZERO, &MINF, 0},
{"log", log, &ONE, &ZERO, 0},
{"log", log, &MONE, &NAN, 0},
{"log", log, &INF, &INF, 0},
{"log10", log10, &NAN, &NAN, 0},
{"log10", log10, &ZERO, &MINF, 0},
{"log10", log10, &MZERO, &MINF, 0},
{"log10", log10, &ONE, &ZERO, 0},
{"log10", log10, &MONE, &NAN, 0},
{"log10", log10, &INF, &INF, 0},
{"log1p", log1p, &NAN, &NAN, 0},
{"log1p", log1p, &ZERO, &ZERO, 0},
{"log1p", log1p, &MZERO, &MZERO, 0},
{"log1p", log1p, &MONE, &MINF, 0},
{"log1p", log1p, &MTWO, &NAN, 0},
{"log1p", log1p, &INF, &INF, 0},
#if !GLIBC2
{"log2", log2, &NAN, &NAN, 0},
{"log2", log2, &ZERO, &MINF, 0},
{"log2", log2, &MZERO, &MINF, 0},
{"log2", log2, &MONE, &NAN, 0},
{"log2", log2, &INF, &INF, 0},
#endif
/* {"fabs", fabs, NAN, NAN, 0}, */
{"fabs", fabs, &ONE, &ONE, 0},
{"fabs", fabs, &MONE, &ONE, 0},
{"fabs", fabs, &ZERO, &ZERO, 0},
{"fabs", fabs, &MZERO, &ZERO, 0},
{"fabs", fabs, &INF, &INF, 0},
{"fabs", fabs, &MINF, &INF, 0},
{"cbrt", cbrt, &NAN, &NAN, 0},
{"cbrt", cbrt, &ZERO, &ZERO, 0},
{"cbrt", cbrt, &MZERO, &MZERO, 0},
{"cbrt", cbrt, &INF, &INF, 0},
{"cbrt", cbrt, &MINF, &MINF, 0},
{"erf", erf, &NAN, &NAN, 0},
{"erf", erf, &ZERO, &ZERO, 0},
{"erf", erf, &MZERO, &MZERO, 0},
{"erf", erf, &INF, &ONE, 0},
{"erf", erf, &MINF, &MONE, 0},
{"erfc", erfc, &NAN, &NAN, 0},
{"erfc", erfc, &INF, &ZERO, 0},
{"erfc", erfc, &MINF, &TWO, 0},
{"gamma", gamma, &NAN, &NAN, 0},
{"gamma", gamma, &INF, &INF, 0},
{"gamma", gamma, &MONE, &NAN, 0},
{"gamma", gamma, &ZERO, &NAN, 0},
{"gamma", gamma, &MINF, &NAN, 0},
#if GLIBC2
{"lgamma", lgamma, &NAN, &NAN, 0},
{"lgamma", lgamma, &INF, &INF, 0},
{"lgamma", lgamma, &MONE, &INF, 0},
{"lgamma", lgamma, &ZERO, &INF, 0},
{"lgamma", lgamma, &MINF, &INF, 0},
#else
{"lgam", lgam, &NAN, &NAN, 0},
{"lgam", lgam, &INF, &INF, 0},
{"lgam", lgam, &MONE, &INF, 0},
{"lgam", lgam, &ZERO, &INF, 0},
{"lgam", lgam, &MINF, &INF, 0},
#endif
{"ceil", ceil, &NAN, &NAN, 0},
{"ceil", ceil, &ZERO, &ZERO, 0},
{"ceil", ceil, &MZERO, &MZERO, 0},
{"ceil", ceil, &INF, &INF, 0},
{"ceil", ceil, &MINF, &MINF, 0},
{"floor", floor, &NAN, &NAN, 0},
{"floor", floor, &ZERO, &ZERO, 0},
{"floor", floor, &MZERO, &MZERO, 0},
{"floor", floor, &INF, &INF, 0},
{"floor", floor, &MINF, &MINF, 0},
{"null", NULL, &ZERO, &ZERO, 0},
};
/* Functions of two variables. */
double atan2 (double, double);
double pow (double, double);
struct twoarguments
{
char *name; /* Name of the function. */
double (*func) (double, double);
double *arg1;
double *arg2;
double *answer;
int thresh;
};
struct twoarguments test2[] =
{
{"atan2", atan2, &ZERO, &ONE, &ZERO, 0},
{"atan2", atan2, &MZERO, &ONE, &MZERO, 0},
{"atan2", atan2, &ZERO, &ZERO, &ZERO, 0},
{"atan2", atan2, &MZERO, &ZERO, &MZERO, 0},
{"atan2", atan2, &ZERO, &MONE, &PI, 0},
{"atan2", atan2, &MZERO, &MONE, &MPI, 0},
{"atan2", atan2, &ZERO, &MZERO, &PI, 0},
{"atan2", atan2, &MZERO, &MZERO, &MPI, 0},
{"atan2", atan2, &ONE, &ZERO, &PIO2, 0},
{"atan2", atan2, &ONE, &MZERO, &PIO2, 0},
{"atan2", atan2, &MONE, &ZERO, &MPIO2, 0},
{"atan2", atan2, &MONE, &MZERO, &MPIO2, 0},
{"atan2", atan2, &ONE, &INF, &ZERO, 0},
{"atan2", atan2, &MONE, &INF, &MZERO, 0},
{"atan2", atan2, &INF, &ONE, &PIO2, 0},
{"atan2", atan2, &INF, &MONE, &PIO2, 0},
{"atan2", atan2, &MINF, &ONE, &MPIO2, 0},
{"atan2", atan2, &MINF, &MONE, &MPIO2, 0},
{"atan2", atan2, &ONE, &MINF, &PI, 0},
{"atan2", atan2, &MONE, &MINF, &MPI, 0},
{"atan2", atan2, &INF, &INF, &PIO4, 0},
{"atan2", atan2, &MINF, &INF, &MPIO4, 0},
{"atan2", atan2, &INF, &MINF, &THPIO4, 0},
{"atan2", atan2, &MINF, &MINF, &MTHPIO4, 0},
{"atan2", atan2, &ONE, &ONE, &PIO4, 0},
{"atan2", atan2, &NAN, &ONE, &NAN, 0},
{"atan2", atan2, &ONE, &NAN, &NAN, 0},
{"atan2", atan2, &NAN, &NAN, &NAN, 0},
{"pow", pow, &ONE, &ZERO, &ONE, 0},
{"pow", pow, &ONE, &MZERO, &ONE, 0},
{"pow", pow, &MONE, &ZERO, &ONE, 0},
{"pow", pow, &MONE, &MZERO, &ONE, 0},
{"pow", pow, &INF, &ZERO, &ONE, 0},
{"pow", pow, &INF, &MZERO, &ONE, 0},
{"pow", pow, &NAN, &ZERO, &ONE, 0},
{"pow", pow, &NAN, &MZERO, &ONE, 0},
{"pow", pow, &TWO, &INF, &INF, 0},
{"pow", pow, &MTWO, &INF, &INF, 0},
{"pow", pow, &HALF, &INF, &ZERO, 0},
{"pow", pow, &MHALF, &INF, &ZERO, 0},
{"pow", pow, &TWO, &MINF, &ZERO, 0},
{"pow", pow, &MTWO, &MINF, &ZERO, 0},
{"pow", pow, &HALF, &MINF, &INF, 0},
{"pow", pow, &MHALF, &MINF, &INF, 0},
{"pow", pow, &INF, &HALF, &INF, 0},
{"pow", pow, &INF, &TWO, &INF, 0},
{"pow", pow, &INF, &MHALF, &ZERO, 0},
{"pow", pow, &INF, &MTWO, &ZERO, 0},
{"pow", pow, &MINF, &THREE, &MINF, 0},
{"pow", pow, &MINF, &TWO, &INF, 0},
{"pow", pow, &MINF, &MTHREE, &MZERO, 0},
{"pow", pow, &MINF, &MTWO, &ZERO, 0},
{"pow", pow, &NAN, &ONE, &NAN, 0},
{"pow", pow, &ONE, &NAN, &NAN, 0},
{"pow", pow, &NAN, &NAN, &NAN, 0},
{"pow", pow, &ONE, &INF, &NAN, 0},
{"pow", pow, &MONE, &INF, &NAN, 0},
{"pow", pow, &ONE, &MINF, &NAN, 0},
{"pow", pow, &MONE, &MINF, &NAN, 0},
{"pow", pow, &MTWO, &HALF, &NAN, 0},
{"pow", pow, &ZERO, &MTHREE, &INF, 0},
{"pow", pow, &MZERO, &MTHREE, &MINF, 0},
{"pow", pow, &ZERO, &MHALF, &INF, 0},
{"pow", pow, &MZERO, &MHALF, &INF, 0},
{"pow", pow, &ZERO, &THREE, &ZERO, 0},
{"pow", pow, &MZERO, &THREE, &MZERO, 0},
{"pow", pow, &ZERO, &HALF, &ZERO, 0},
{"pow", pow, &MZERO, &HALF, &ZERO, 0},
{"null", NULL, &ZERO, &ZERO, &ZERO, 0},
};
/* Integer functions of one variable. */
int isnan (double);
int signbit (double);
struct intans
{
char *name; /* Name of the function. */
int (*func) (double);
double *arg1;
int ianswer;
};
struct intans test3[] =
{
{"isfinite", isfinite, &ZERO, 1},
{"isfinite", isfinite, &INF, 0},
{"isfinite", isfinite, &MINF, 0},
{"isnan", isnan, &NAN, 1},
{"isnan", isnan, &INF, 0},
{"isnan", isnan, &ZERO, 0},
{"isnan", isnan, &MZERO, 0},
{"signbit", signbit, &MZERO, 1},
{"signbit", signbit, &MONE, 1},
{"signbit", signbit, &ZERO, 0},
{"signbit", signbit, &ONE, 0},
{"signbit", signbit, &MINF, 1},
{"signbit", signbit, &INF, 0},
{"null", NULL, &ZERO, 0},
};
static volatile double x1;
static volatile double x2;
static volatile double y;
static volatile double answer;
void
pvec(x)
double x;
{
union
{
double d;
unsigned short s[4];
} u;
int i;
u.d = x;
for (i = 0; i < 4; i++)
printf ("0x%04x ", u.s[i]);
printf ("\n");
}
int
main ()
{
int i, nerrors, k, ianswer, ntests;
double (*fun1) (double);
double (*fun2) (double, double);
int (*fun3) (double);
double e;
union
{
double d;
char c[8];
} u, v;
ZERO = 0.0;
MZERO = NEGZERO;
HALF = 0.5;
MHALF = -HALF;
ONE = 1.0;
MONE = -ONE;
TWO = 2.0;
MTWO = -TWO;
THREE = 3.0;
MTHREE = -THREE;
INF = INFINITY;
MINF = -INFINITY;
MPI = -PI;
PIO2 = 0.5 * PI;
MPIO2 = -PIO2;
PIO4 = 0.5 * PIO2;
MPIO4 = -PIO4;
THPIO4 = 3.0 * PIO4;
MTHPIO4 = -THPIO4;
nerrors = 0;
ntests = 0;
i = 0;
for (;;)
{
fun1 = test1[i].func;
if (fun1 == NULL)
break;
x1 = *(test1[i].arg1);
y = (*(fun1)) (x1);
answer = *(test1[i].answer);
if (test1[i].thresh == 0)
{
v.d = answer;
u.d = y;
if (memcmp(u.c, v.c, 8) != 0)
{
if( isnan(v.d) && isnan(u.d) )
goto nxttest1;
goto wrongone;
}
else
goto nxttest1;
}
if (y != answer)
{
e = y - answer;
if (answer != 0.0)
e = e / answer;
if (e < 0)
e = -e;
if (e > test1[i].thresh * MACHEP)
{
wrongone:
printf ("%s (%.16e) = %.16e\n should be %.16e\n",
test1[i].name, x1, y, answer);
nerrors += 1;
}
}
nxttest1:
ntests += 1;
i += 1;
}
i = 0;
for (;;)
{
fun2 = test2[i].func;
if (fun2 == NULL)
break;
x1 = *(test2[i].arg1);
x2 = *(test2[i].arg2);
y = (*(fun2)) (x1, x2);
answer = *(test2[i].answer);
if (test2[i].thresh == 0)
{
v.d = answer;
u.d = y;
if (memcmp(u.c, v.c, 8) != 0)
{
if( isnan(v.d) && isnan(u.d) )
goto nxttest2;
#if 0
if( isnan(v.d) )
pvec(v.d);
if( isnan(u.d) )
pvec(u.d);
#endif
goto wrongtwo;
}
else
goto nxttest2;
}
if (y != answer)
{
e = y - answer;
if (answer != 0.0)
e = e / answer;
if (e < 0)
e = -e;
if (e > test2[i].thresh * MACHEP)
{
wrongtwo:
printf ("%s (%.16e, %.16e) = %.16e\n should be %.16e\n",
test2[i].name, x1, x2, y, answer);
nerrors += 1;
}
}
nxttest2:
ntests += 1;
i += 1;
}
i = 0;
for (;;)
{
fun3 = test3[i].func;
if (fun3 == NULL)
break;
x1 = *(test3[i].arg1);
k = (*(fun3)) (x1);
ianswer = test3[i].ianswer;
if (k != ianswer)
{
printf ("%s (%.16e) = %d\n should be. %d\n",
test3[i].name, x1, k, ianswer);
nerrors += 1;
}
ntests += 1;
i += 1;
}
printf ("testvect: %d errors in %d tests\n", nerrors, ntests);
exit (0);
}

View File

@@ -0,0 +1,203 @@
/* exp.c
*
* Exponential function
*
*
*
* SYNOPSIS:
*
* double x, y, exp();
*
* y = exp( x );
*
*
*
* DESCRIPTION:
*
* Returns e (2.71828...) raised to the x power.
*
* Range reduction is accomplished by separating the argument
* into an integer k and fraction f such that
*
* x k f
* e = 2 e.
*
* A Pade' form 1 + 2x P(x**2)/( Q(x**2) - P(x**2) )
* of degree 2/3 is used to approximate exp(f) in the basic
* interval [-0.5, 0.5].
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC +- 88 50000 2.8e-17 7.0e-18
* IEEE +- 708 40000 2.0e-16 5.6e-17
*
*
* Error amplification in the exponential function can be
* a serious matter. The error propagation involves
* exp( X(1+delta) ) = exp(X) ( 1 + X*delta + ... ),
* which shows that a 1 lsb error in representing X produces
* a relative error of X times 1 lsb in the function.
* While the routine gives an accurate result for arguments
* that are exactly represented by a double precision
* computer number, the result contains amplified roundoff
* error for large arguments not exactly represented.
*
*
* ERROR MESSAGES:
*
* message condition value returned
* exp underflow x < MINLOG 0.0
* exp overflow x > MAXLOG INFINITY
*
*/
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
*/
/* Exponential function */
#include "mconf.h"
#ifdef UNK
const static double P[] = {
1.26177193074810590878E-4,
3.02994407707441961300E-2,
9.99999999999999999910E-1,
};
const static double Q[] = {
3.00198505138664455042E-6,
2.52448340349684104192E-3,
2.27265548208155028766E-1,
2.00000000000000000009E0,
};
const static double C1 = 6.93145751953125E-1;
const static double C2 = 1.42860682030941723212E-6;
#endif
#ifdef DEC
static unsigned short P[] = {
0035004,0047156,0127442,0057502,
0036770,0033210,0063121,0061764,
0040200,0000000,0000000,0000000,
};
static unsigned short Q[] = {
0033511,0072665,0160662,0176377,
0036045,0070715,0124105,0132777,
0037550,0134114,0142077,0001637,
0040400,0000000,0000000,0000000,
};
static unsigned short sc1[] = {0040061,0071000,0000000,0000000};
#define C1 (*(double *)sc1)
static unsigned short sc2[] = {0033277,0137216,0075715,0057117};
#define C2 (*(double *)sc2)
#endif
#ifdef IBMPC
static unsigned short P[] = {
0x4be8,0xd5e4,0x89cd,0x3f20,
0x2c7e,0x0cca,0x06d1,0x3f9f,
0x0000,0x0000,0x0000,0x3ff0,
};
static unsigned short Q[] = {
0x5fa0,0xbc36,0x2eb6,0x3ec9,
0xb6c0,0xb508,0xae39,0x3f64,
0xe074,0x9887,0x1709,0x3fcd,
0x0000,0x0000,0x0000,0x4000,
};
static unsigned short sc1[] = {0x0000,0x0000,0x2e40,0x3fe6};
#define C1 (*(double *)sc1)
static unsigned short sc2[] = {0xabca,0xcf79,0xf7d1,0x3eb7};
#define C2 (*(double *)sc2)
#endif
#ifdef MIEEE
static unsigned short P[] = {
0x3f20,0x89cd,0xd5e4,0x4be8,
0x3f9f,0x06d1,0x0cca,0x2c7e,
0x3ff0,0x0000,0x0000,0x0000,
};
static unsigned short Q[] = {
0x3ec9,0x2eb6,0xbc36,0x5fa0,
0x3f64,0xae39,0xb508,0xb6c0,
0x3fcd,0x1709,0x9887,0xe074,
0x4000,0x0000,0x0000,0x0000,
};
static unsigned short sc1[] = {0x3fe6,0x2e40,0x0000,0x0000};
#define C1 (*(double *)sc1)
static unsigned short sc2[] = {0x3eb7,0xf7d1,0xcf79,0xabca};
#define C2 (*(double *)sc2)
#endif
#ifdef ANSIPROT
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
extern double floor ( double );
extern double ldexp ( double, int );
extern int isnan ( double );
extern int isfinite ( double );
#else
double polevl(), p1evl(), floor(), ldexp();
int isnan(), isfinite();
#endif
extern double LOGE2, LOG2E, MAXLOG, MINLOG, MAXNUM;
#ifdef INFINITIES
extern double INFINITY;
#endif
double exp(x)
double x;
{
double px, xx;
int n;
#ifdef NANS
if( isnan(x) )
return(x);
#endif
if( x > MAXLOG)
{
#ifdef INFINITIES
return( INFINITY );
#else
mtherr( "exp", OVERFLOW );
return( MAXNUM );
#endif
}
if( x < MINLOG )
{
#ifndef INFINITIES
mtherr( "exp", UNDERFLOW );
#endif
return(0.0);
}
/* Express e**x = e**g 2**n
* = e**g e**( n loge(2) )
* = e**( g + n loge(2) )
*/
px = floor( LOG2E * x + 0.5 ); /* floor() truncates toward -infinity. */
n = px;
x -= px * C1;
x -= px * C2;
/* rational approximation for exponential
* of the fractional part:
* e**x = 1 + 2x P(x**2)/( Q(x**2) - P(x**2) )
*/
xx = x * x;
px = x * polevl( xx, P, 2 );
x = px/( polevl( xx, Q, 3 ) - px );
x = 1.0 + 2.0 * x;
/* multiply by power of 2 */
x = ldexp( x, n );
return(x);
}

View File

@@ -0,0 +1,223 @@
/* exp10.c
*
* Base 10 exponential function
* (Common antilogarithm)
*
*
*
* SYNOPSIS:
*
* double x, y, exp10();
*
* y = exp10( x );
*
*
*
* DESCRIPTION:
*
* Returns 10 raised to the x power.
*
* Range reduction is accomplished by expressing the argument
* as 10**x = 2**n 10**f, with |f| < 0.5 log10(2).
* The Pade' form
*
* 1 + 2x P(x**2)/( Q(x**2) - P(x**2) )
*
* is used to approximate 10**f.
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* IEEE -307,+307 30000 2.2e-16 5.5e-17
* Test result from an earlier version (2.1):
* DEC -38,+38 70000 3.1e-17 7.0e-18
*
* ERROR MESSAGES:
*
* message condition value returned
* exp10 underflow x < -MAXL10 0.0
* exp10 overflow x > MAXL10 MAXNUM
*
* DEC arithmetic: MAXL10 = 38.230809449325611792.
* IEEE arithmetic: MAXL10 = 308.2547155599167.
*
*/
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1991, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
#ifdef UNK
const static double P[] = {
4.09962519798587023075E-2,
1.17452732554344059015E1,
4.06717289936872725516E2,
2.39423741207388267439E3,
};
const static double Q[] = {
/* 1.00000000000000000000E0,*/
8.50936160849306532625E1,
1.27209271178345121210E3,
2.07960819286001865907E3,
};
/* const static double LOG102 = 3.01029995663981195214e-1; */
const static double LOG210 = 3.32192809488736234787e0;
const static double LG102A = 3.01025390625000000000E-1;
const static double LG102B = 4.60503898119521373889E-6;
/* const static double MAXL10 = 38.230809449325611792; */
const static double MAXL10 = 308.2547155599167;
#endif
#ifdef DEC
static unsigned short P[] = {
0037047,0165657,0114061,0067234,
0041073,0166243,0123052,0144643,
0042313,0055720,0024032,0047443,
0043025,0121714,0070232,0050007,
};
static unsigned short Q[] = {
/*0040200,0000000,0000000,0000000,*/
0041652,0027756,0071216,0050075,
0042637,0001367,0077263,0136017,
0043001,0174673,0024157,0133416,
};
/*
static unsigned short L102[] = {0037632,0020232,0102373,0147770};
#define LOG102 *(double *)L102
*/
static unsigned short L210[] = {0040524,0115170,0045715,0015613};
#define LOG210 *(double *)L210
static unsigned short L102A[] = {0037632,0020000,0000000,0000000,};
#define LG102A *(double *)L102A
static unsigned short L102B[] = {0033632,0102373,0147767,0114220,};
#define LG102B *(double *)L102B
static unsigned short MXL[] = {0041430,0166131,0047761,0154130,};
#define MAXL10 ( *(double *)MXL )
#endif
#ifdef IBMPC
static unsigned short P[] = {
0x2dd4,0xf306,0xfd75,0x3fa4,
0x5934,0x74c5,0x7d94,0x4027,
0x49e4,0x0503,0x6b7a,0x4079,
0x4a01,0x8e13,0xb479,0x40a2,
};
static unsigned short Q[] = {
/*0x0000,0x0000,0x0000,0x3ff0,*/
0xca08,0xce51,0x45fd,0x4055,
0x7782,0xefd6,0xe05e,0x4093,
0xf6e2,0x650d,0x3f37,0x40a0,
};
/*
static unsigned short L102[] = {0x79ff,0x509f,0x4413,0x3fd3};
#define LOG102 *(double *)L102
*/
static unsigned short L210[] = {0xa371,0x0979,0x934f,0x400a};
#define LOG210 *(double *)L210
static unsigned short L102A[] = {0x0000,0x0000,0x4400,0x3fd3,};
#define LG102A *(double *)L102A
static unsigned short L102B[] = {0xf312,0x79fe,0x509f,0x3ed3,};
#define LG102B *(double *)L102B
const static double MAXL10 = 308.2547155599167;
#endif
#ifdef MIEEE
static unsigned short P[] = {
0x3fa4,0xfd75,0xf306,0x2dd4,
0x4027,0x7d94,0x74c5,0x5934,
0x4079,0x6b7a,0x0503,0x49e4,
0x40a2,0xb479,0x8e13,0x4a01,
};
static unsigned short Q[] = {
/*0x3ff0,0x0000,0x0000,0x0000,*/
0x4055,0x45fd,0xce51,0xca08,
0x4093,0xe05e,0xefd6,0x7782,
0x40a0,0x3f37,0x650d,0xf6e2,
};
/*
static unsigned short L102[] = {0x3fd3,0x4413,0x509f,0x79ff};
#define LOG102 *(double *)L102
*/
static unsigned short L210[] = {0x400a,0x934f,0x0979,0xa371};
#define LOG210 *(double *)L210
static unsigned short L102A[] = {0x3fd3,0x4400,0x0000,0x0000,};
#define LG102A *(double *)L102A
static unsigned short L102B[] = {0x3ed3,0x509f,0x79fe,0xf312,};
#define LG102B *(double *)L102B
const static double MAXL10 = 308.2547155599167;
#endif
#ifdef ANSIPROT
extern double floor ( double );
extern double ldexp ( double, int );
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
extern int isnan ( double );
extern int isfinite ( double );
#else
double floor(), ldexp(), polevl(), p1evl();
int isnan(), isfinite();
#endif
extern double MAXNUM;
#ifdef INFINITIES
extern double INFINITY;
#endif
double exp10(x)
double x;
{
double px, xx;
short n;
#ifdef NANS
if( isnan(x) )
return(x);
#endif
if( x > MAXL10 )
{
#ifdef INFINITIES
return( INFINITY );
#else
mtherr( "exp10", OVERFLOW );
return( MAXNUM );
#endif
}
if( x < -MAXL10 ) /* Would like to use MINLOG but can't */
{
#ifndef INFINITIES
mtherr( "exp10", UNDERFLOW );
#endif
return(0.0);
}
/* Express 10**x = 10**g 2**n
* = 10**g 10**( n log10(2) )
* = 10**( g + n log10(2) )
*/
px = floor( LOG210 * x + 0.5 );
n = px;
x -= px * LG102A;
x -= px * LG102B;
/* rational approximation for exponential
* of the fractional part:
* 10**x = 1 + 2x P(x**2)/( Q(x**2) - P(x**2) )
*/
xx = x * x;
px = x * polevl( xx, P, 3 );
x = px/( p1evl( xx, Q, 3 ) - px );
x = 1.0 + ldexp( x, 1 );
/* multiply by power of 2 */
x = ldexp( x, n );
return(x);
}

View File

@@ -0,0 +1,183 @@
/* exp2.c
*
* Base 2 exponential function
*
*
*
* SYNOPSIS:
*
* double x, y, exp2();
*
* y = exp2( x );
*
*
*
* DESCRIPTION:
*
* Returns 2 raised to the x power.
*
* Range reduction is accomplished by separating the argument
* into an integer k and fraction f such that
* x k f
* 2 = 2 2.
*
* A Pade' form
*
* 1 + 2x P(x**2) / (Q(x**2) - x P(x**2) )
*
* approximates 2**x in the basic range [-0.5, 0.5].
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* IEEE -1022,+1024 30000 1.8e-16 5.4e-17
*
*
* See exp.c for comments on error amplification.
*
*
* ERROR MESSAGES:
*
* message condition value returned
* exp underflow x < -MAXL2 0.0
* exp overflow x > MAXL2 MAXNUM
*
* For DEC arithmetic, MAXL2 = 127.
* For IEEE arithmetic, MAXL2 = 1024.
*/
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
#ifdef UNK
const static double P[] = {
2.30933477057345225087E-2,
2.02020656693165307700E1,
1.51390680115615096133E3,
};
const static double Q[] = {
/* 1.00000000000000000000E0,*/
2.33184211722314911771E2,
4.36821166879210612817E3,
};
#define MAXL2 1024.0
#define MINL2 -1024.0
#endif
#ifdef DEC
static unsigned short P[] = {
0036675,0027102,0122327,0053227,
0041241,0116724,0115412,0157355,
0042675,0036404,0101733,0132226,
};
static unsigned short Q[] = {
/*0040200,0000000,0000000,0000000,*/
0042151,0027450,0077732,0160744,
0043210,0100661,0077550,0056560,
};
#define MAXL2 127.0
#define MINL2 -127.0
#endif
#ifdef IBMPC
static unsigned short P[] = {
0xead3,0x549a,0xa5c8,0x3f97,
0x5bde,0x9361,0x33ba,0x4034,
0x7693,0x907b,0xa7a0,0x4097,
};
static unsigned short Q[] = {
/*0x0000,0x0000,0x0000,0x3ff0,*/
0x5c3c,0x0ffb,0x25e5,0x406d,
0x0bae,0x2fed,0x1036,0x40b1,
};
#define MAXL2 1024.0
#define MINL2 -1022.0
#endif
#ifdef MIEEE
static unsigned short P[] = {
0x3f97,0xa5c8,0x549a,0xead3,
0x4034,0x33ba,0x9361,0x5bde,
0x4097,0xa7a0,0x907b,0x7693,
};
static unsigned short Q[] = {
/*0x3ff0,0x0000,0x0000,0x0000,*/
0x406d,0x25e5,0x0ffb,0x5c3c,
0x40b1,0x1036,0x2fed,0x0bae,
};
#define MAXL2 1024.0
#define MINL2 -1022.0
#endif
#ifdef ANSIPROT
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
extern double floor ( double );
extern double ldexp ( double, int );
extern int isnan ( double );
extern int isfinite ( double );
#else
double polevl(), p1evl(), floor(), ldexp();
int isnan(), isfinite();
#endif
#ifdef INFINITIES
extern double INFINITY;
#endif
extern double MAXNUM;
double exp2(x)
double x;
{
double px, xx;
short n;
#ifdef NANS
if( isnan(x) )
return(x);
#endif
if( x > MAXL2)
{
#ifdef INFINITIES
return( INFINITY );
#else
mtherr( "exp2", OVERFLOW );
return( MAXNUM );
#endif
}
if( x < MINL2 )
{
#ifndef INFINITIES
mtherr( "exp2", UNDERFLOW );
#endif
return(0.0);
}
xx = x; /* save x */
/* separate into integer and fractional parts */
px = floor(x+0.5);
n = px;
x = x - px;
/* rational approximation
* exp2(x) = 1 + 2xP(xx)/(Q(xx) - P(xx))
* where xx = x**2
*/
xx = x * x;
px = x * polevl( xx, P, 2 );
x = px / ( p1evl( xx, Q, 2 ) - px );
x = 1.0 + ldexp( x, 1 );
/* scale by power of 2 */
x = ldexp( x, n );
return(x);
}

View File

@@ -0,0 +1,56 @@
/* fabs.c
*
* Absolute value
*
*
*
* SYNOPSIS:
*
* double x, y;
*
* y = fabs( x );
*
*
*
* DESCRIPTION:
*
* Returns the absolute value of the argument.
*
*/
#include "mconf.h"
/* Avoid using UNK if possible. */
#ifdef UNK
#if BIGENDIAN
#define MIEEE 1
#else
#define IBMPC 1
#endif
#endif
double fabs(x)
double x;
{
union
{
double d;
short i[4];
} u;
u.d = x;
#ifdef IBMPC
u.i[3] &= 0x7fff;
#endif
#ifdef MIEEE
u.i[0] &= 0x7fff;
#endif
#ifdef DEC
u.i[3] &= 0x7fff;
#endif
#ifdef UNK
if( u.d < 0 )
u.d = -u.d;
#endif
return( u.d );
}

View File

@@ -0,0 +1,453 @@
/* ceil()
* floor()
* frexp()
* ldexp()
* signbit()
* isnan()
* isfinite()
*
* Floating point numeric utilities
*
*
*
* SYNOPSIS:
*
* double ceil(), floor(), frexp(), ldexp();
* int signbit(), isnan(), isfinite();
* double x, y;
* int expnt, n;
*
* y = floor(x);
* y = ceil(x);
* y = frexp( x, &expnt );
* y = ldexp( x, n );
* n = signbit(x);
* n = isnan(x);
* n = isfinite(x);
*
*
*
* DESCRIPTION:
*
* All four routines return a double precision floating point
* result.
*
* floor() returns the largest integer less than or equal to x.
* It truncates toward minus infinity.
*
* ceil() returns the smallest integer greater than or equal
* to x. It truncates toward plus infinity.
*
* frexp() extracts the exponent from x. It returns an integer
* power of two to expnt and the significand between 0.5 and 1
* to y. Thus x = y * 2**expn.
*
* ldexp() multiplies x by 2**n.
*
* signbit(x) returns 1 if the sign bit of x is 1, else 0.
*
* These functions are part of the standard C run time library
* for many but not all C compilers. The ones supplied are
* written in C for either DEC or IEEE arithmetic. They should
* be used only if your compiler library does not already have
* them.
*
* The IEEE versions assume that denormal numbers are implemented
* in the arithmetic. Some modifications will be required if
* the arithmetic has abrupt rather than gradual underflow.
*/
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
#ifdef UNK
/* ceil(), floor(), frexp(), ldexp() may need to be rewritten. */
#undef UNK
#if BIGENDIAN
#define MIEEE 1
#else
#define IBMPC 1
#endif
#endif
#ifdef DEC
#define EXPMSK 0x807f
#define MEXP 255
#define NBITS 56
#endif
#ifdef IBMPC
#define EXPMSK 0x800f
#define MEXP 0x7ff
#define NBITS 53
#endif
#ifdef MIEEE
#define EXPMSK 0x800f
#define MEXP 0x7ff
#define NBITS 53
#endif
extern double MAXNUM, NEGZERO;
#ifdef ANSIPROT
double floor ( double );
int isnan ( double );
int isfinite ( double );
double ldexp ( double, int );
#else
double floor();
int isnan(), isfinite();
double ldexp();
#endif
double ceil(x)
double x;
{
double y;
#ifdef UNK
mtherr( "ceil", DOMAIN );
return(0.0);
#endif
#ifdef NANS
if( isnan(x) )
return( x );
#endif
#ifdef INFINITIES
if(!isfinite(x))
return(x);
#endif
y = floor(x);
if( y < x )
y += 1.0;
#ifdef MINUSZERO
if( y == 0.0 && x < 0.0 )
return( NEGZERO );
#endif
return(y);
}
/* Bit clearing masks: */
static unsigned short bmask[] = {
0xffff,
0xfffe,
0xfffc,
0xfff8,
0xfff0,
0xffe0,
0xffc0,
0xff80,
0xff00,
0xfe00,
0xfc00,
0xf800,
0xf000,
0xe000,
0xc000,
0x8000,
0x0000,
};
double floor(x)
double x;
{
union
{
double y;
unsigned short sh[4];
} u;
unsigned short *p;
int e;
#ifdef UNK
mtherr( "floor", DOMAIN );
return(0.0);
#endif
#ifdef NANS
if( isnan(x) )
return( x );
#endif
#ifdef INFINITIES
if(!isfinite(x))
return(x);
#endif
#ifdef MINUSZERO
if(x == 0.0L)
return(x);
#endif
u.y = x;
/* find the exponent (power of 2) */
#ifdef DEC
p = (unsigned short *)&u.sh[0];
e = (( *p >> 7) & 0377) - 0201;
p += 3;
#endif
#ifdef IBMPC
p = (unsigned short *)&u.sh[3];
e = (( *p >> 4) & 0x7ff) - 0x3ff;
p -= 3;
#endif
#ifdef MIEEE
p = (unsigned short *)&u.sh[0];
e = (( *p >> 4) & 0x7ff) - 0x3ff;
p += 3;
#endif
if( e < 0 )
{
if( u.y < 0.0 )
return( -1.0 );
else
return( 0.0 );
}
e = (NBITS -1) - e;
/* clean out 16 bits at a time */
while( e >= 16 )
{
#ifdef IBMPC
*p++ = 0;
#endif
#ifdef DEC
*p-- = 0;
#endif
#ifdef MIEEE
*p-- = 0;
#endif
e -= 16;
}
/* clear the remaining bits */
if( e > 0 )
*p &= bmask[e];
if( (x < 0) && (u.y != x) )
u.y -= 1.0;
return(u.y);
}
double frexp( x, pw2 )
double x;
int *pw2;
{
union
{
double y;
unsigned short sh[4];
} u;
int i;
#ifdef DENORMAL
int k;
#endif
short *q;
u.y = x;
#ifdef UNK
mtherr( "frexp", DOMAIN );
return(0.0);
#endif
#ifdef IBMPC
q = (short *)&u.sh[3];
#endif
#ifdef DEC
q = (short *)&u.sh[0];
#endif
#ifdef MIEEE
q = (short *)&u.sh[0];
#endif
/* find the exponent (power of 2) */
#ifdef DEC
i = ( *q >> 7) & 0377;
if( i == 0 )
{
*pw2 = 0;
return(0.0);
}
i -= 0200;
*pw2 = i;
*q &= 0x807f; /* strip all exponent bits */
*q |= 040000; /* mantissa between 0.5 and 1 */
return(u.y);
#endif
#ifdef IBMPC
i = ( *q >> 4) & 0x7ff;
if( i != 0 )
goto ieeedon;
#endif
#ifdef MIEEE
i = *q >> 4;
i &= 0x7ff;
if( i != 0 )
goto ieeedon;
#ifdef DENORMAL
#else
*pw2 = 0;
return(0.0);
#endif
#endif
#ifndef DEC
/* Number is denormal or zero */
#ifdef DENORMAL
if( u.y == 0.0 )
{
*pw2 = 0;
return( 0.0 );
}
/* Handle denormal number. */
do
{
u.y *= 2.0;
i -= 1;
k = ( *q >> 4) & 0x7ff;
}
while( k == 0 );
i = i + k;
#endif /* DENORMAL */
ieeedon:
i -= 0x3fe;
*pw2 = i;
*q &= 0x800f;
*q |= 0x3fe0;
return( u.y );
#endif
}
double ldexp( x, pw2 )
double x;
int pw2;
{
union
{
double y;
unsigned short sh[4];
} u;
short *q;
int e;
#ifdef UNK
mtherr( "ldexp", DOMAIN );
return(0.0);
#endif
u.y = x;
#ifdef DEC
q = (short *)&u.sh[0];
e = ( *q >> 7) & 0377;
if( e == 0 )
return(0.0);
#else
#ifdef IBMPC
q = (short *)&u.sh[3];
#endif
#ifdef MIEEE
q = (short *)&u.sh[0];
#endif
while( (e = (*q & 0x7ff0) >> 4) == 0 )
{
if( u.y == 0.0 )
{
return( 0.0 );
}
/* Input is denormal. */
if( pw2 > 0 )
{
u.y *= 2.0;
pw2 -= 1;
}
if( pw2 < 0 )
{
if( pw2 < -53 )
return(0.0);
u.y /= 2.0;
pw2 += 1;
}
if( pw2 == 0 )
return(u.y);
}
#endif /* not DEC */
e += pw2;
/* Handle overflow */
#ifdef DEC
if( e > MEXP )
return( MAXNUM );
#else
if( e >= MEXP )
return( 2.0*MAXNUM );
#endif
/* Handle denormalized results */
if( e < 1 )
{
#ifdef DENORMAL
if( e < -53 )
return(0.0);
*q &= 0x800f;
*q |= 0x10;
/* For denormals, significant bits may be lost even
when dividing by 2. Construct 2^-(1-e) so the result
is obtained with only one multiplication. */
u.y *= ldexp(1.0, e-1);
return(u.y);
#else
return(0.0);
#endif
}
else
{
#ifdef DEC
*q &= 0x807f; /* strip all exponent bits */
*q |= (e & 0xff) << 7;
#else
*q &= 0x800f;
*q |= (e & 0x7ff) << 4;
#endif
return(u.y);
}
}

View File

@@ -0,0 +1,289 @@
# MSDOS Microsoft C makefile for Cephes library
CFLAGS=/c
# For large memory model:
#CFLAGS=/c /AL
# Add /FPa to the CFLAGS if you want to use the fast software FPa arithmetic.
#
# Use the following with /FPa if you do not want to use the 80x87 coprocessor
# or software emulator.
#polevl.obj: polevl.c mconf.h
# cl /c /Ox polevl.c
#
# Use the following instead if you want to use an 80x87 chip or
# software emulator for maximum accuracy computation of the
# polynomial expansions:
polevl.obj: polevl.asm mconf.h
masm polevl.asm/r;
floor.obj: floor.asm
masm floor.asm;
#floor.obj: floor.c mconf.h
# cl $(CFLAGS) floor.c
acosh.obj: acosh.c mconf.h
cl $(CFLAGS) acosh.c
airy.obj: airy.c mconf.h
cl $(CFLAGS) airy.c
asin.obj: asin.c mconf.h
cl $(CFLAGS) asin.c
asinh.obj: asinh.c mconf.h
cl $(CFLAGS) asinh.c
atan.obj: atan.c mconf.h
cl $(CFLAGS) atan.c
atanh.obj: atanh.c mconf.h
cl $(CFLAGS) atanh.c
asinh.obj: asinh.c mconf.h
cl $(CFLAGS) asinh.c
bdtr.obj: bdtr.c mconf.h
cl $(CFLAGS) bdtr.c
beta.obj: beta.c mconf.h
cl $(CFLAGS) beta.c
btdtr.obj: btdtr.c mconf.h
cl $(CFLAGS) btdtr.c
cbrt.obj: cbrt.c mconf.h
cl $(CFLAGS) cbrt.c
chbevl.obj: chbevl.c mconf.h
cl $(CFLAGS) chbevl.c
chdtr.obj: chdtr.c mconf.h
cl $(CFLAGS) chdtr.c
clog.obj: clog.c mconf.h
cl $(CFLAGS) clog.c
cmplx.obj: cmplx.c mconf.h
cl $(CFLAGS) cmplx.c
const.obj: const.c mconf.h
cl $(CFLAGS) const.c
cosh.obj: cosh.c mconf.h
cl $(CFLAGS) cosh.c
dawsn.obj: dawsn.c mconf.h
cl $(CFLAGS) dawsn.c
drand.obj: drand.c mconf.h
cl $(CFLAGS) drand.c
ellie.obj: ellie.c mconf.h
cl $(CFLAGS) ellie.c
ellik.obj: ellik.c mconf.h
cl $(CFLAGS) ellik.c
ellpe.obj: ellpe.c mconf.h
cl $(CFLAGS) ellpe.c
ellpj.obj: ellpj.c mconf.h
cl $(CFLAGS) ellpj.c
ellpk.obj: ellpk.c mconf.h
cl $(CFLAGS) ellpk.c
exp.obj: exp.c mconf.h
cl $(CFLAGS) exp.c
exp10.obj: exp10.c mconf.h
cl $(CFLAGS) exp10.c
exp2.obj: exp2.c mconf.h
cl $(CFLAGS) exp2.c
expn.obj: expn.c mconf.h
cl $(CFLAGS) expn.c
fabs.obj: fabs.c mconf.h
cl $(CFLAGS) fabs.c
fac.obj: fac.c mconf.h
cl $(CFLAGS) fac.c
fdtr.obj: fdtr.c mconf.h
cl $(CFLAGS) fdtr.c
fresnl.obj: fresnl.c mconf.h
cl $(CFLAGS) fresnl.c
gamma.obj: gamma.c mconf.h
cl $(CFLAGS) gamma.c
gdtr.obj: gdtr.c mconf.h
cl $(CFLAGS) gdtr.c
hyp2f1.obj: hyp2f1.c mconf.h
cl $(CFLAGS) hyp2f1.c
hyperg.obj: hyperg.c mconf.h
cl $(CFLAGS) hyperg.c
i0.obj: i0.c mconf.h
cl $(CFLAGS) i0.c
i1.obj: i1.c mconf.h
cl $(CFLAGS) i1.c
igam.obj: igam.c mconf.h
cl $(CFLAGS) igam.c
igami.obj: igami.c mconf.h
cl $(CFLAGS) igami.c
incbet.obj: incbet.c mconf.h
cl $(CFLAGS) incbet.c
incbi.obj: incbi.c mconf.h
cl $(CFLAGS) incbi.c
isnan.obj: isnan.c mconf.h
cl $(CFLAGS) isnan.c
iv.obj: iv.c mconf.h
cl $(CFLAGS) iv.c
j0.obj: j0.c mconf.h
cl $(CFLAGS) j0.c
j1.obj: j1.c mconf.h
cl $(CFLAGS) j1.c
jn.obj: jn.c mconf.h
cl $(CFLAGS) jn.c
jv.obj: jv.c mconf.h
cl $(CFLAGS) jv.c
k0.obj: k0.c mconf.h
cl $(CFLAGS) k0.c
k1.obj: k1.c mconf.h
cl $(CFLAGS) k1.c
kn.obj: kn.c mconf.h
cl $(CFLAGS) kn.c
log.obj: log.c mconf.h
cl $(CFLAGS) log.c
log2.obj: log2.c mconf.h
cl $(CFLAGS) log2.c
log10.obj: log10.c mconf.h
cl $(CFLAGS) log10.c
mtherr.obj: mtherr.c mconf.h
cl $(CFLAGS) mtherr.c
nbdtr.obj: nbdtr.c mconf.h
cl $(CFLAGS) nbdtr.c
ndtr.obj: ndtr.c mconf.h
cl $(CFLAGS) ndtr.c
ndtri.obj: ndtri.c mconf.h
cl $(CFLAGS) ndtri.c
pdtr.obj: pdtr.c mconf.h
cl $(CFLAGS) pdtr.c
pow.obj: pow.c mconf.h
cl $(CFLAGS) pow.c
powi.obj: powi.c mconf.h
cl $(CFLAGS) powi.c
psi.obj: psi.c mconf.h
cl $(CFLAGS) psi.c
rgamma.obj: rgamma.c mconf.h
cl $(CFLAGS) rgamma.c
round.obj: round.c mconf.h
cl $(CFLAGS) round.c
setprec.obj: setprec.87
masm setprec.87;
shichi.obj: shichi.c mconf.h
cl $(CFLAGS) shichi.c
sici.obj: sici.c mconf.h
cl $(CFLAGS) sici.c
sin.obj: sin.c mconf.h
cl $(CFLAGS) sin.c
sindg.obj: sindg.c mconf.h
cl $(CFLAGS) sindg.c
sinh.obj: sinh.c mconf.h
cl $(CFLAGS) sinh.c
spence.obj: spence.c mconf.h
cl $(CFLAGS) spence.c
sqrt.obj: sqrt.87
masm sqrt.87;
#sqrt.obj: sqrt.c
# cl $(CFLAGS) sqrt.c
stdtr.obj: stdtr.c mconf.h
cl $(CFLAGS) stdtr.c
struve.obj: struve.c mconf.h
cl $(CFLAGS) struve.c
tan.obj: tan.c mconf.h
cl $(CFLAGS) tan.c
tandg.obj: tandg.c mconf.h
cl $(CFLAGS) tandg.c
tanh.obj: tanh.c mconf.h
cl $(CFLAGS) tanh.c
yn.obj: yn.c mconf.h
cl $(CFLAGS) yn.c
zeta.obj: zeta.c mconf.h
cl $(CFLAGS) zeta.c
zetac.obj: zetac.c mconf.h
cl $(CFLAGS) zetac.c
polyn.obj: polyn.c mconf.h
cl $(CFLAGS) polyn.c
polmisc.obj: polmisc.c mconf.h
cl $(CFLAGS) polmisc.c
unity.obj: unity.c mconf.h
cl $(CFLAGS) unity.c
fti.lib: acosh.obj airy.obj asin.obj asinh.obj atan.obj atanh.obj bdtr.obj \
beta.obj btdtr.obj cbrt.obj chbevl.obj chdtr.obj clog.obj \
cmplx.obj const.obj cosh.obj dawsn.obj drand.obj ellie.obj ellik.obj \
ellpe.obj ellpj.obj ellpk.obj exp.obj exp10.obj \
exp2.obj expn.obj fabs.obj fac.obj fdtr.obj floor.obj fresnl.obj gamma.obj \
gdtr.obj hyp2f1.obj hyperg.obj i0.c i1.c igam.c igami.obj incbet.obj \
incbi.obj isnan.obj iv.obj j0.obj j1.obj jn.obj jv.obj k0.obj k1.obj \
kn.obj log.obj log2.obj log10.obj mtherr.obj nbdtr.obj ndtr.obj ndtri.obj \
pdtr.obj polevl.obj polmisc.obj polyn.obj pow.obj powi.obj psi.obj \
rgamma.obj round.obj shichi.obj sici.obj sin.obj sindg.obj sinh.obj \
spence.obj sqrt.obj stdtr.obj setprec.obj struve.obj tan.obj \
tandg.obj tanh.obj unity.obj yn.obj zeta.obj zetac.obj \
mconf.h
lib @ftilib.rsp

View File

@@ -0,0 +1,17 @@
fti
y
acosh airy asin asinh atan &
atanh bdtr beta btdtr cbrt chbevl &
chdtr clog cmplx const &
cosh dawsn drand ellie ellik ellpe ellpk &
ellpj exp exp2 exp10 expn fac &
fdtr fresnl gamma gdtr &
hyperg hyp2f1 incbet incbi igam igami isnan &
iv i0 i1 jn jv j0 j1 k0 k1 kn log log2 log10 &
mtherr nbdtr ndtr ndtri pdtr &
polmisc polyn pow powi psi &
rgamma round shichi sici sin sindg &
sinh spence sqrt stdtr struve tan tandg &
tanh unity yn zeta zetac floor fabs polevl
fti.lst
fti

View File

@@ -0,0 +1,237 @@
/* isnan()
* signbit()
* isfinite()
*
* Floating point numeric utilities
*
*
*
* SYNOPSIS:
*
* double ceil(), floor(), frexp(), ldexp();
* int signbit(), isnan(), isfinite();
* double x, y;
* int expnt, n;
*
* y = floor(x);
* y = ceil(x);
* y = frexp( x, &expnt );
* y = ldexp( x, n );
* n = signbit(x);
* n = isnan(x);
* n = isfinite(x);
*
*
*
* DESCRIPTION:
*
* All four routines return a double precision floating point
* result.
*
* floor() returns the largest integer less than or equal to x.
* It truncates toward minus infinity.
*
* ceil() returns the smallest integer greater than or equal
* to x. It truncates toward plus infinity.
*
* frexp() extracts the exponent from x. It returns an integer
* power of two to expnt and the significand between 0.5 and 1
* to y. Thus x = y * 2**expn.
*
* ldexp() multiplies x by 2**n.
*
* signbit(x) returns 1 if the sign bit of x is 1, else 0.
*
* These functions are part of the standard C run time library
* for many but not all C compilers. The ones supplied are
* written in C for either DEC or IEEE arithmetic. They should
* be used only if your compiler library does not already have
* them.
*
* The IEEE versions assume that denormal numbers are implemented
* in the arithmetic. Some modifications will be required if
* the arithmetic has abrupt rather than gradual underflow.
*/
/*
Cephes Math Library Release 2.3: March, 1995
Copyright 1984, 1995 by Stephen L. Moshier
*/
#include "mconf.h"
#ifdef UNK
/* ceil(), floor(), frexp(), ldexp() may need to be rewritten. */
#undef UNK
#if BIGENDIAN
#define MIEEE 1
#else
#define IBMPC 1
#endif
#endif
/* Return 1 if the sign bit of x is 1, else 0. */
int signbit(x)
double x;
{
union
{
double d;
short s[4];
int i[2];
} u;
u.d = x;
if( sizeof(int) == 4 )
{
#ifdef IBMPC
return( u.i[1] < 0 );
#endif
#ifdef DEC
return( u.s[3] < 0 );
#endif
#ifdef MIEEE
return( u.i[0] < 0 );
#endif
}
else
{
#ifdef IBMPC
return( u.s[3] < 0 );
#endif
#ifdef DEC
return( u.s[3] < 0 );
#endif
#ifdef MIEEE
return( u.s[0] < 0 );
#endif
}
}
/* Return 1 if x is a number that is Not a Number, else return 0. */
int isnan(x)
double x;
{
#ifdef NANS
union
{
double d;
unsigned short s[4];
unsigned int i[2];
} u;
u.d = x;
if( sizeof(int) == 4 )
{
#ifdef IBMPC
if( ((u.i[1] & 0x7ff00000) == 0x7ff00000)
&& (((u.i[1] & 0x000fffff) != 0) || (u.i[0] != 0)))
return 1;
#endif
#ifdef DEC
if( (u.s[1] & 0x7fff) == 0)
{
if( (u.s[2] | u.s[1] | u.s[0]) != 0 )
return(1);
}
#endif
#ifdef MIEEE
if( ((u.i[0] & 0x7ff00000) == 0x7ff00000)
&& (((u.i[0] & 0x000fffff) != 0) || (u.i[1] != 0)))
return 1;
#endif
return(0);
}
else
{ /* size int not 4 */
#ifdef IBMPC
if( (u.s[3] & 0x7ff0) == 0x7ff0)
{
if( ((u.s[3] & 0x000f) | u.s[2] | u.s[1] | u.s[0]) != 0 )
return(1);
}
#endif
#ifdef DEC
if( (u.s[3] & 0x7fff) == 0)
{
if( (u.s[2] | u.s[1] | u.s[0]) != 0 )
return(1);
}
#endif
#ifdef MIEEE
if( (u.s[0] & 0x7ff0) == 0x7ff0)
{
if( ((u.s[0] & 0x000f) | u.s[1] | u.s[2] | u.s[3]) != 0 )
return(1);
}
#endif
return(0);
} /* size int not 4 */
#else
/* No NANS. */
return(0);
#endif
}
/* Return 1 if x is not infinite and is not a NaN. */
int isfinite(x)
double x;
{
#ifdef INFINITIES
union
{
double d;
unsigned short s[4];
unsigned int i[2];
} u;
u.d = x;
if( sizeof(int) == 4 )
{
#ifdef IBMPC
if( (u.i[1] & 0x7ff00000) != 0x7ff00000)
return 1;
#endif
#ifdef DEC
if( (u.s[3] & 0x7fff) != 0)
return 1;
#endif
#ifdef MIEEE
if( (u.i[0] & 0x7ff00000) != 0x7ff00000)
return 1;
#endif
return(0);
}
else
{
#ifdef IBMPC
if( (u.s[3] & 0x7ff0) != 0x7ff0)
return 1;
#endif
#ifdef DEC
if( (u.s[3] & 0x7fff) != 0)
return 1;
#endif
#ifdef MIEEE
if( (u.s[0] & 0x7ff0) != 0x7ff0)
return 1;
#endif
return(0);
}
#else
/* No INFINITY. */
return(1);
#endif
}

View File

@@ -0,0 +1,341 @@
/* log.c
*
* Natural logarithm
*
*
*
* SYNOPSIS:
*
* double x, y, log();
*
* y = log( x );
*
*
*
* DESCRIPTION:
*
* Returns the base e (2.718...) logarithm of x.
*
* The argument is separated into its exponent and fractional
* parts. If the exponent is between -1 and +1, the logarithm
* of the fraction is approximated by
*
* log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x).
*
* Otherwise, setting z = 2(x-1)/x+1),
*
* log(x) = z + z**3 P(z)/Q(z).
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* IEEE 0.5, 2.0 150000 1.44e-16 5.06e-17
* IEEE +-MAXNUM 30000 1.20e-16 4.78e-17
* DEC 0, 10 170000 1.8e-17 6.3e-18
*
* In the tests over the interval [+-MAXNUM], the logarithms
* of the random arguments were uniformly distributed over
* [0, MAXLOG].
*
* ERROR MESSAGES:
*
* log singularity: x = 0; returns -INFINITY
* log domain: x < 0; returns NAN
*/
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
static char fname[] = {"log"};
/* Coefficients for log(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
* 1/sqrt(2) <= x < sqrt(2)
*/
#ifdef UNK
const static double P[] = {
1.01875663804580931796E-4,
4.97494994976747001425E-1,
4.70579119878881725854E0,
1.44989225341610930846E1,
1.79368678507819816313E1,
7.70838733755885391666E0,
};
const static double Q[] = {
/* 1.00000000000000000000E0, */
1.12873587189167450590E1,
4.52279145837532221105E1,
8.29875266912776603211E1,
7.11544750618563894466E1,
2.31251620126765340583E1,
};
#endif
#ifdef DEC
static unsigned short P[] = {
0037777,0127270,0162547,0057274,
0041001,0054665,0164317,0005341,
0041451,0034104,0031640,0105773,
0041677,0011276,0123617,0160135,
0041701,0126603,0053215,0117250,
0041420,0115777,0135206,0030232,
};
static unsigned short Q[] = {
/*0040200,0000000,0000000,0000000,*/
0041220,0144332,0045272,0174241,
0041742,0164566,0035720,0130431,
0042246,0126327,0166065,0116357,
0042372,0033420,0157525,0124560,
0042271,0167002,0066537,0172303,
0041730,0164777,0113711,0044407,
};
#endif
#ifdef IBMPC
static unsigned short P[] = {
0x1bb0,0x93c3,0xb4c2,0x3f1a,
0x52f2,0x3f56,0xd6f5,0x3fdf,
0x6911,0xed92,0xd2ba,0x4012,
0xeb2e,0xc63e,0xff72,0x402c,
0xc84d,0x924b,0xefd6,0x4031,
0xdcf8,0x7d7e,0xd563,0x401e,
};
static unsigned short Q[] = {
/*0x0000,0x0000,0x0000,0x3ff0,*/
0xef8e,0xae97,0x9320,0x4026,
0xc033,0x4e19,0x9d2c,0x4046,
0xbdbd,0xa326,0xbf33,0x4054,
0xae21,0xeb5e,0xc9e2,0x4051,
0x25b2,0x9e1f,0x200a,0x4037,
};
#endif
#ifdef MIEEE
static unsigned short P[] = {
0x3f1a,0xb4c2,0x93c3,0x1bb0,
0x3fdf,0xd6f5,0x3f56,0x52f2,
0x4012,0xd2ba,0xed92,0x6911,
0x402c,0xff72,0xc63e,0xeb2e,
0x4031,0xefd6,0x924b,0xc84d,
0x401e,0xd563,0x7d7e,0xdcf8,
};
static unsigned short Q[] = {
/*0x3ff0,0x0000,0x0000,0x0000,*/
0x4026,0x9320,0xae97,0xef8e,
0x4046,0x9d2c,0x4e19,0xc033,
0x4054,0xbf33,0xa326,0xbdbd,
0x4051,0xc9e2,0xeb5e,0xae21,
0x4037,0x200a,0x9e1f,0x25b2,
};
#endif
/* Coefficients for log(x) = z + z**3 P(z)/Q(z),
* where z = 2(x-1)/(x+1)
* 1/sqrt(2) <= x < sqrt(2)
*/
#ifdef UNK
const static double R[3] = {
-7.89580278884799154124E-1,
1.63866645699558079767E1,
-6.41409952958715622951E1,
};
const static double S[3] = {
/* 1.00000000000000000000E0,*/
-3.56722798256324312549E1,
3.12093766372244180303E2,
-7.69691943550460008604E2,
};
#endif
#ifdef DEC
static unsigned short R[12] = {
0140112,0020756,0161540,0072035,
0041203,0013743,0114023,0155527,
0141600,0044060,0104421,0050400,
};
static unsigned short S[12] = {
/*0040200,0000000,0000000,0000000,*/
0141416,0130152,0017543,0064122,
0042234,0006000,0104527,0020155,
0142500,0066110,0146631,0174731,
};
#endif
#ifdef IBMPC
static unsigned short R[12] = {
0x0e84,0xdc6c,0x443d,0xbfe9,
0x7b6b,0x7302,0x62fc,0x4030,
0x2a20,0x1122,0x0906,0xc050,
};
static unsigned short S[12] = {
/*0x0000,0x0000,0x0000,0x3ff0,*/
0x6d0a,0x43ec,0xd60d,0xc041,
0xe40e,0x112a,0x8180,0x4073,
0x3f3b,0x19b3,0x0d89,0xc088,
};
#endif
#ifdef MIEEE
static unsigned short R[12] = {
0xbfe9,0x443d,0xdc6c,0x0e84,
0x4030,0x62fc,0x7302,0x7b6b,
0xc050,0x0906,0x1122,0x2a20,
};
static unsigned short S[12] = {
/*0x3ff0,0x0000,0x0000,0x0000,*/
0xc041,0xd60d,0x43ec,0x6d0a,
0x4073,0x8180,0x112a,0xe40e,
0xc088,0x0d89,0x19b3,0x3f3b,
};
#endif
#ifdef ANSIPROT
extern double frexp ( double, int * );
extern double ldexp ( double, int );
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
extern int isnan ( double );
extern int isfinite ( double );
#else
double frexp(), ldexp(), polevl(), p1evl();
int isnan(), isfinite();
#endif
#define SQRTH 0.70710678118654752440
extern double INFINITY, NAN;
double log(x)
double x;
{
int e;
#ifdef DEC
short *q;
#endif
double y, z;
#ifdef NANS
if( isnan(x) )
return(x);
#endif
#ifdef INFINITIES
if( x == INFINITY )
return(x);
#endif
/* Test for domain */
if( x <= 0.0 )
{
if( x == 0.0 )
{
mtherr( fname, SING );
return( -INFINITY );
}
else
{
mtherr( fname, DOMAIN );
return( NAN );
}
}
/* separate mantissa from exponent */
#ifdef DEC
q = (short *)&x;
e = *q; /* short containing exponent */
e = ((e >> 7) & 0377) - 0200; /* the exponent */
*q &= 0177; /* strip exponent from x */
*q |= 040000; /* x now between 0.5 and 1 */
#endif
/* Note, frexp is used so that denormal numbers
* will be handled properly.
*/
#ifdef IBMPC
x = frexp( x, &e );
/*
q = (short *)&x;
q += 3;
e = *q;
e = ((e >> 4) & 0x0fff) - 0x3fe;
*q &= 0x0f;
*q |= 0x3fe0;
*/
#endif
/* Equivalent C language standard library function: */
#ifdef UNK
x = frexp( x, &e );
#endif
#ifdef MIEEE
x = frexp( x, &e );
#endif
/* logarithm using log(x) = z + z**3 P(z)/Q(z),
* where z = 2(x-1)/x+1)
*/
if( (e > 2) || (e < -2) )
{
if( x < SQRTH )
{ /* 2( 2x-1 )/( 2x+1 ) */
e -= 1;
z = x - 0.5;
y = 0.5 * z + 0.5;
}
else
{ /* 2 (x-1)/(x+1) */
z = x - 0.5;
z -= 0.5;
y = 0.5 * x + 0.5;
}
x = z / y;
/* rational form */
z = x*x;
z = x * ( z * polevl( z, R, 2 ) / p1evl( z, S, 3 ) );
y = e;
z = z - y * 2.121944400546905827679e-4;
z = z + x;
z = z + e * 0.693359375;
goto ldone;
}
/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */
if( x < SQRTH )
{
e -= 1;
x = ldexp( x, 1 ) - 1.0; /* 2x - 1 */
}
else
{
x = x - 1.0;
}
/* rational form */
z = x*x;
#if DEC
y = x * ( z * polevl( x, P, 5 ) / p1evl( x, Q, 6 ) );
#else
y = x * ( z * polevl( x, P, 5 ) / p1evl( x, Q, 5 ) );
#endif
if( e )
y = y - e * 2.121944400546905827679e-4;
y = y - ldexp( z, -1 ); /* y - 0.5 * z */
z = x + y;
if( e )
z = z + e * 0.693359375;
ldone:
return( z );
}

View File

@@ -0,0 +1,250 @@
/* log10.c
*
* Common logarithm
*
*
*
* SYNOPSIS:
*
* double x, y, log10();
*
* y = log10( x );
*
*
*
* DESCRIPTION:
*
* Returns logarithm to the base 10 of x.
*
* The argument is separated into its exponent and fractional
* parts. The logarithm of the fraction is approximated by
*
* log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x).
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* IEEE 0.5, 2.0 30000 1.5e-16 5.0e-17
* IEEE 0, MAXNUM 30000 1.4e-16 4.8e-17
* DEC 1, MAXNUM 50000 2.5e-17 6.0e-18
*
* In the tests over the interval [1, MAXNUM], the logarithms
* of the random arguments were uniformly distributed over
* [0, MAXLOG].
*
* ERROR MESSAGES:
*
* log10 singularity: x = 0; returns -INFINITY
* log10 domain: x < 0; returns NAN
*/
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
static char fname[] = {"log10"};
/* Coefficients for log(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
* 1/sqrt(2) <= x < sqrt(2)
*/
#ifdef UNK
const static double P[] = {
4.58482948458143443514E-5,
4.98531067254050724270E-1,
6.56312093769992875930E0,
2.97877425097986925891E1,
6.06127134467767258030E1,
5.67349287391754285487E1,
1.98892446572874072159E1
};
const static double Q[] = {
/* 1.00000000000000000000E0, */
1.50314182634250003249E1,
8.27410449222435217021E1,
2.20664384982121929218E2,
3.07254189979530058263E2,
2.14955586696422947765E2,
5.96677339718622216300E1
};
#endif
#ifdef DEC
static unsigned short P[] = {
0034500,0046473,0051374,0135174,
0037777,0037566,0145712,0150321,
0040722,0002426,0031543,0123107,
0041356,0046513,0170752,0004346,
0041562,0071553,0023536,0163343,
0041542,0170221,0024316,0114216,
0041237,0016454,0046611,0104602
};
static unsigned short Q[] = {
/*0040200,0000000,0000000,0000000,*/
0041160,0100260,0067736,0102424,
0041645,0075552,0036563,0147072,
0042134,0125025,0021132,0025320,
0042231,0120211,0046030,0103271,
0042126,0172241,0052151,0120426,
0041556,0125702,0072116,0047103
};
#endif
#ifdef IBMPC
static unsigned short P[] = {
0x974f,0x6a5f,0x09a7,0x3f08,
0x5a1a,0xd979,0xe7ee,0x3fdf,
0x74c9,0xc66c,0x40a2,0x401a,
0x411d,0x7e3d,0xc9a9,0x403d,
0xdcdc,0x64eb,0x4e6d,0x404e,
0xd312,0x2519,0x5e12,0x404c,
0x3130,0x89b1,0xe3a5,0x4033
};
static unsigned short Q[] = {
/*0x0000,0x0000,0x0000,0x3ff0,*/
0xd0a2,0x0dfb,0x1016,0x402e,
0x79c7,0x47ae,0xaf6d,0x4054,
0x455a,0xa44b,0x9542,0x406b,
0x10d7,0x2983,0x3411,0x4073,
0x3423,0x2a8d,0xde94,0x406a,
0xc9c8,0x4e89,0xd578,0x404d
};
#endif
#ifdef MIEEE
static unsigned short P[] = {
0x3f08,0x09a7,0x6a5f,0x974f,
0x3fdf,0xe7ee,0xd979,0x5a1a,
0x401a,0x40a2,0xc66c,0x74c9,
0x403d,0xc9a9,0x7e3d,0x411d,
0x404e,0x4e6d,0x64eb,0xdcdc,
0x404c,0x5e12,0x2519,0xd312,
0x4033,0xe3a5,0x89b1,0x3130
};
static unsigned short Q[] = {
0x402e,0x1016,0x0dfb,0xd0a2,
0x4054,0xaf6d,0x47ae,0x79c7,
0x406b,0x9542,0xa44b,0x455a,
0x4073,0x3411,0x2983,0x10d7,
0x406a,0xde94,0x2a8d,0x3423,
0x404d,0xd578,0x4e89,0xc9c8
};
#endif
#define SQRTH 0.70710678118654752440
#define L102A 3.0078125E-1
#define L102B 2.48745663981195213739E-4
#define L10EA 4.3359375E-1
#define L10EB 7.00731903251827651129E-4
#ifdef ANSIPROT
extern double frexp ( double, int * );
extern double ldexp ( double, int );
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
extern int isnan ( double );
extern int isfinite ( double );
#else
double frexp(), ldexp(), polevl(), p1evl();
int isnan(), isfinite();
#endif
extern double LOGE2, SQRT2, INFINITY, NAN;
double log10(x)
double x;
{
VOLATILE double z;
double y;
#ifdef DEC
short *q;
#endif
int e;
#ifdef NANS
if( isnan(x) )
return(x);
#endif
#ifdef INFINITIES
if( x == INFINITY )
return(x);
#endif
/* Test for domain */
if( x <= 0.0 )
{
if( x == 0.0 )
{
mtherr( fname, SING );
return( -INFINITY );
}
else
{
mtherr( fname, DOMAIN );
return( NAN );
}
}
/* separate mantissa from exponent */
#ifdef DEC
q = (short *)&x;
e = *q; /* short containing exponent */
e = ((e >> 7) & 0377) - 0200; /* the exponent */
*q &= 0177; /* strip exponent from x */
*q |= 040000; /* x now between 0.5 and 1 */
#endif
#ifdef IBMPC
x = frexp( x, &e );
/*
q = (short *)&x;
q += 3;
e = *q;
e = ((e >> 4) & 0x0fff) - 0x3fe;
*q &= 0x0f;
*q |= 0x3fe0;
*/
#endif
/* Equivalent C language standard library function: */
#ifdef UNK
x = frexp( x, &e );
#endif
#ifdef MIEEE
x = frexp( x, &e );
#endif
/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */
if( x < SQRTH )
{
e -= 1;
x = ldexp( x, 1 ) - 1.0; /* 2x - 1 */
}
else
{
x = x - 1.0;
}
/* rational form */
z = x*x;
y = x * ( z * polevl( x, P, 6 ) / p1evl( x, Q, 6 ) );
y = y - ldexp( z, -1 ); /* y - 0.5 * x**2 */
/* multiply log of fraction by log10(e)
* and base 2 exponent by log10(2)
*/
z = (x + y) * L10EB; /* accumulate terms in order of size */
z += y * L10EA;
z += x * L10EA;
z += e * L102B;
z += e * L102A;
return( z );
}

View File

@@ -0,0 +1,348 @@
/* log2.c
*
* Base 2 logarithm
*
*
*
* SYNOPSIS:
*
* double x, y, log2();
*
* y = log2( x );
*
*
*
* DESCRIPTION:
*
* Returns the base 2 logarithm of x.
*
* The argument is separated into its exponent and fractional
* parts. If the exponent is between -1 and +1, the base e
* logarithm of the fraction is approximated by
*
* log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x).
*
* Otherwise, setting z = 2(x-1)/x+1),
*
* log(x) = z + z**3 P(z)/Q(z).
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* IEEE 0.5, 2.0 30000 2.0e-16 5.5e-17
* IEEE exp(+-700) 40000 1.3e-16 4.6e-17
*
* In the tests over the interval [exp(+-700)], the logarithms
* of the random arguments were uniformly distributed.
*
* ERROR MESSAGES:
*
* log2 singularity: x = 0; returns -INFINITY
* log2 domain: x < 0; returns NAN
*/
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
static char fname[] = {"log2"};
/* Coefficients for log(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
* 1/sqrt(2) <= x < sqrt(2)
*/
#ifdef UNK
const static double P[] = {
1.01875663804580931796E-4,
4.97494994976747001425E-1,
4.70579119878881725854E0,
1.44989225341610930846E1,
1.79368678507819816313E1,
7.70838733755885391666E0,
};
const static double Q[] = {
/* 1.00000000000000000000E0, */
1.12873587189167450590E1,
4.52279145837532221105E1,
8.29875266912776603211E1,
7.11544750618563894466E1,
2.31251620126765340583E1,
};
#define LOG2EA 0.44269504088896340735992
#endif
#ifdef DEC
static unsigned short P[] = {
0037777,0127270,0162547,0057274,
0041001,0054665,0164317,0005341,
0041451,0034104,0031640,0105773,
0041677,0011276,0123617,0160135,
0041701,0126603,0053215,0117250,
0041420,0115777,0135206,0030232,
};
static unsigned short Q[] = {
/*0040200,0000000,0000000,0000000,*/
0041220,0144332,0045272,0174241,
0041742,0164566,0035720,0130431,
0042246,0126327,0166065,0116357,
0042372,0033420,0157525,0124560,
0042271,0167002,0066537,0172303,
0041730,0164777,0113711,0044407,
};
static unsigned short L[5] = {0037742,0124354,0122560,0057703};
#define LOG2EA (*(double *)(&L[0]))
#endif
#ifdef IBMPC
static unsigned short P[] = {
0x1bb0,0x93c3,0xb4c2,0x3f1a,
0x52f2,0x3f56,0xd6f5,0x3fdf,
0x6911,0xed92,0xd2ba,0x4012,
0xeb2e,0xc63e,0xff72,0x402c,
0xc84d,0x924b,0xefd6,0x4031,
0xdcf8,0x7d7e,0xd563,0x401e,
};
static unsigned short Q[] = {
/*0x0000,0x0000,0x0000,0x3ff0,*/
0xef8e,0xae97,0x9320,0x4026,
0xc033,0x4e19,0x9d2c,0x4046,
0xbdbd,0xa326,0xbf33,0x4054,
0xae21,0xeb5e,0xc9e2,0x4051,
0x25b2,0x9e1f,0x200a,0x4037,
};
static unsigned short L[5] = {0x0bf8,0x94ae,0x551d,0x3fdc};
#define LOG2EA (*(double *)(&L[0]))
#endif
#ifdef MIEEE
static unsigned short P[] = {
0x3f1a,0xb4c2,0x93c3,0x1bb0,
0x3fdf,0xd6f5,0x3f56,0x52f2,
0x4012,0xd2ba,0xed92,0x6911,
0x402c,0xff72,0xc63e,0xeb2e,
0x4031,0xefd6,0x924b,0xc84d,
0x401e,0xd563,0x7d7e,0xdcf8,
};
static unsigned short Q[] = {
/*0x3ff0,0x0000,0x0000,0x0000,*/
0x4026,0x9320,0xae97,0xef8e,
0x4046,0x9d2c,0x4e19,0xc033,
0x4054,0xbf33,0xa326,0xbdbd,
0x4051,0xc9e2,0xeb5e,0xae21,
0x4037,0x200a,0x9e1f,0x25b2,
};
static unsigned short L[5] = {0x3fdc,0x551d,0x94ae,0x0bf8};
#define LOG2EA (*(double *)(&L[0]))
#endif
/* Coefficients for log(x) = z + z**3 P(z)/Q(z),
* where z = 2(x-1)/(x+1)
* 1/sqrt(2) <= x < sqrt(2)
*/
#ifdef UNK
const static double R[3] = {
-7.89580278884799154124E-1,
1.63866645699558079767E1,
-6.41409952958715622951E1,
};
const static double S[3] = {
/* 1.00000000000000000000E0,*/
-3.56722798256324312549E1,
3.12093766372244180303E2,
-7.69691943550460008604E2,
};
/* log2(e) - 1 */
#define LOG2EA 0.44269504088896340735992
#endif
#ifdef DEC
static unsigned short R[12] = {
0140112,0020756,0161540,0072035,
0041203,0013743,0114023,0155527,
0141600,0044060,0104421,0050400,
};
static unsigned short S[12] = {
/*0040200,0000000,0000000,0000000,*/
0141416,0130152,0017543,0064122,
0042234,0006000,0104527,0020155,
0142500,0066110,0146631,0174731,
};
/* log2(e) - 1 */
#define LOG2EA 0.44269504088896340735992L
#endif
#ifdef IBMPC
static unsigned short R[12] = {
0x0e84,0xdc6c,0x443d,0xbfe9,
0x7b6b,0x7302,0x62fc,0x4030,
0x2a20,0x1122,0x0906,0xc050,
};
static unsigned short S[12] = {
/*0x0000,0x0000,0x0000,0x3ff0,*/
0x6d0a,0x43ec,0xd60d,0xc041,
0xe40e,0x112a,0x8180,0x4073,
0x3f3b,0x19b3,0x0d89,0xc088,
};
#endif
#ifdef MIEEE
static unsigned short R[12] = {
0xbfe9,0x443d,0xdc6c,0x0e84,
0x4030,0x62fc,0x7302,0x7b6b,
0xc050,0x0906,0x1122,0x2a20,
};
static unsigned short S[12] = {
/*0x3ff0,0x0000,0x0000,0x0000,*/
0xc041,0xd60d,0x43ec,0x6d0a,
0x4073,0x8180,0x112a,0xe40e,
0xc088,0x0d89,0x19b3,0x3f3b,
};
#endif
#ifdef ANSIPROT
extern double frexp ( double, int * );
extern double ldexp ( double, int );
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
extern int isnan ( double );
extern int isfinite ( double );
#else
double frexp(), ldexp(), polevl(), p1evl();
int isnan(), isfinite();
#endif
#define SQRTH 0.70710678118654752440
extern double LOGE2, INFINITY, NAN;
double log2(x)
double x;
{
int e;
double y;
VOLATILE double z;
#ifdef DEC
short *q;
#endif
#ifdef NANS
if( isnan(x) )
return(x);
#endif
#ifdef INFINITIES
if( x == INFINITY )
return(x);
#endif
/* Test for domain */
if( x <= 0.0 )
{
if( x == 0.0 )
{
mtherr( fname, SING );
return( -INFINITY );
}
else
{
mtherr( fname, DOMAIN );
return( NAN );
}
}
/* separate mantissa from exponent */
#ifdef DEC
q = (short *)&x;
e = *q; /* short containing exponent */
e = ((e >> 7) & 0377) - 0200; /* the exponent */
*q &= 0177; /* strip exponent from x */
*q |= 040000; /* x now between 0.5 and 1 */
#endif
/* Note, frexp is used so that denormal numbers
* will be handled properly.
*/
#ifdef IBMPC
x = frexp( x, &e );
/*
q = (short *)&x;
q += 3;
e = *q;
e = ((e >> 4) & 0x0fff) - 0x3fe;
*q &= 0x0f;
*q |= 0x3fe0;
*/
#endif
/* Equivalent C language standard library function: */
#ifdef UNK
x = frexp( x, &e );
#endif
#ifdef MIEEE
x = frexp( x, &e );
#endif
/* logarithm using log(x) = z + z**3 P(z)/Q(z),
* where z = 2(x-1)/x+1)
*/
if( (e > 2) || (e < -2) )
{
if( x < SQRTH )
{ /* 2( 2x-1 )/( 2x+1 ) */
e -= 1;
z = x - 0.5;
y = 0.5 * z + 0.5;
}
else
{ /* 2 (x-1)/(x+1) */
z = x - 0.5;
z -= 0.5;
y = 0.5 * x + 0.5;
}
x = z / y;
z = x*x;
y = x * ( z * polevl( z, R, 2 ) / p1evl( z, S, 3 ) );
goto ldone;
}
/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */
if( x < SQRTH )
{
e -= 1;
x = ldexp( x, 1 ) - 1.0; /* 2x - 1 */
}
else
{
x = x - 1.0;
}
z = x*x;
#if DEC
y = x * ( z * polevl( x, P, 5 ) / p1evl( x, Q, 6 ) ) - ldexp( z, -1 );
#else
y = x * ( z * polevl( x, P, 5 ) / p1evl( x, Q, 5 ) ) - ldexp( z, -1 );
#endif
ldone:
/* Multiply log of fraction by log2(e)
* and base 2 exponent by 1
*
* ***CAUTION***
*
* This sequence of operations is critical and it may
* be horribly defeated by some compiler optimizers.
*/
z = y * LOG2EA;
z += x * LOG2EA;
z += y;
z += x;
z += e;
return( z );
}

View File

@@ -0,0 +1,199 @@
/* mconf.h
*
* Common include file for math routines
*
*
*
* SYNOPSIS:
*
* #include "mconf.h"
*
*
*
* DESCRIPTION:
*
* This file contains definitions for error codes that are
* passed to the common error handling routine mtherr()
* (which see).
*
* The file also includes a conditional assembly definition
* for the type of computer arithmetic (IEEE, DEC, Motorola
* IEEE, or UNKnown).
*
* For Digital Equipment PDP-11 and VAX computers, certain
* IBM systems, and others that use numbers with a 56-bit
* significand, the symbol DEC should be defined. In this
* mode, most floating point constants are given as arrays
* of octal integers to eliminate decimal to binary conversion
* errors that might be introduced by the compiler.
*
* For little-endian computers, such as IBM PC, that follow the
* IEEE Standard for Binary Floating Point Arithmetic (ANSI/IEEE
* Std 754-1985), the symbol IBMPC should be defined. These
* numbers have 53-bit significands. In this mode, constants
* are provided as arrays of hexadecimal 16 bit integers.
*
* Big-endian IEEE format is denoted MIEEE. On some RISC
* systems such as Sun SPARC, double precision constants
* must be stored on 8-byte address boundaries. Since integer
* arrays may be aligned differently, the MIEEE configuration
* may fail on such machines.
*
* To accommodate other types of computer arithmetic, all
* constants are also provided in a normal decimal radix
* which one can hope are correctly converted to a suitable
* format by the available C language compiler. To invoke
* this mode, define the symbol UNK.
*
* An important difference among these modes is a predefined
* set of machine arithmetic constants for each. The numbers
* MACHEP (the machine roundoff error), MAXNUM (largest number
* represented), and several other parameters are preset by
* the configuration symbol. Check the file const.c to
* ensure that these values are correct for your computer.
*
* Configurations NANS, INFINITIES, MINUSZERO, and DENORMAL
* may fail on many systems. Verify that they are supposed
* to work on your computer.
*/
/*
Cephes Math Library Release 2.3: June, 1995
Copyright 1984, 1987, 1989, 1995 by Stephen L. Moshier
*/
/* Define if the `long double' type works. */
#define HAVE_LONG_DOUBLE 1
/* Define as the return type of signal handlers (int or void). */
#define RETSIGTYPE void
/* Define if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define if your processor stores words with the most significant
byte first (like Motorola and SPARC, unlike Intel and VAX). */
/* #undef WORDS_BIGENDIAN */
/* Define if floating point words are bigendian. */
/* #undef FLOAT_WORDS_BIGENDIAN */
/* The number of bytes in a int. */
#define SIZEOF_INT 4
/* Define if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Name of package */
#define PACKAGE "cephes"
/* Version number of package */
#define VERSION "2.7"
/* Constant definitions for math error conditions
*/
#define DOMAIN 1 /* argument domain error */
#define SING 2 /* argument singularity */
#define OVERFLOW 3 /* overflow range error */
#define UNDERFLOW 4 /* underflow range error */
#define TLOSS 5 /* total loss of precision */
#define PLOSS 6 /* partial loss of precision */
#define EDOM 33
#define ERANGE 34
/* Complex numeral. */
typedef struct
{
double r;
double i;
} cmplx;
#ifdef HAVE_LONG_DOUBLE
/* Long double complex numeral. */
typedef struct
{
long double r;
long double i;
} cmplxl;
#endif
/* Type of computer arithmetic */
/* PDP-11, Pro350, VAX:
*/
/* #define DEC 1 */
/* Intel IEEE, low order words come first:
*/
/* #define IBMPC 1 */
/* Motorola IEEE, high order words come first
* (Sun 680x0 workstation):
*/
/* #define MIEEE 1 */
/* UNKnown arithmetic, invokes coefficients given in
* normal decimal format. Beware of range boundary
* problems (MACHEP, MAXLOG, etc. in const.c) and
* roundoff problems in pow.c:
* (Sun SPARCstation)
*/
#define UNK 1
/* If you define UNK, then be sure to set BIGENDIAN properly. */
#ifdef FLOAT_WORDS_BIGENDIAN
#define BIGENDIAN 1
#else
#define BIGENDIAN 0
#endif
/* Define this `volatile' if your compiler thinks
* that floating point arithmetic obeys the associative
* and distributive laws. It will defeat some optimizations
* (but probably not enough of them).
*
* #define VOLATILE volatile
*/
#define VOLATILE
/* For 12-byte long doubles on an i386, pad a 16-bit short 0
* to the end of real constants initialized by integer arrays.
*
* #define XPD 0,
*
* Otherwise, the type is 10 bytes long and XPD should be
* defined blank (e.g., Microsoft C).
*
* #define XPD
*/
#define XPD 0,
/* Define to support tiny denormal numbers, else undefine. */
#define DENORMAL 1
/* Define to ask for infinity support, else undefine. */
#define INFINITIES 1
/* Define to ask for support of numbers that are Not-a-Number,
else undefine. This may automatically define INFINITIES in some files. */
#define NANS 1
/* Define to distinguish between -0.0 and +0.0. */
#define MINUSZERO 1
/* Define 1 for ANSI C atan2() function
See atan.c and clog.c. */
#define ANSIC 1
/* Get ANSI function prototypes, if you want them. */
#if 1
/* #ifdef __STDC__ */
#define ANSIPROT 1
int mtherr ( char *, int );
#else
int mtherr();
#endif
/* Variable for error reporting. See mtherr.c. */
extern int merror;

View File

@@ -0,0 +1,122 @@
/* Program to test range reduction of trigonometry functions
*
* -- Steve Moshier
*/
#include "mconf.h"
#ifdef ANSIPROT
extern double floor ( double );
extern double ldexp ( double, int );
extern double sin ( double );
#else
double floor(), ldexp(), sin();
#endif
#define TPI 6.283185307179586476925
main()
{
char s[40];
double a, n, t, x, y, z;
int lflg;
x = TPI/4.0;
t = 1.0;
loop:
t = 2.0 * t;
/* Stop testing at a point beyond which the integer part of
* x/2pi cannot be represented exactly by a double precision number.
* The library trigonometry functions will probably give up long before
* this point is reached.
*/
if( t > 1.0e16 )
exit(0);
/* Adjust the following to choose a nontrivial x
* where test function(x) has a slope of about 1 or more.
*/
x = TPI * t + 0.5;
z = x;
lflg = 0;
inlup:
/* floor() returns the largest integer less than its argument.
* If you do not have this, or AINT(), then you may convert x/TPI
* to a long integer and then back to double; but in that case
* x will be limited to the largest value that will fit into a
* long integer.
*/
n = floor( z/TPI );
/* Carefully subtract 2 pi n from x.
* This is done by subtracting n * 2**k in such a way that there
* is no arithmetic cancellation error at any step. The k are the
* bits in the number 2 pi.
*
* If you do not have ldexp(), then you may multiply or
* divide n by an appropriate power of 2 after each step.
* For example:
* a = z - 4*n;
* a -= 2*n;
* n /= 4;
* a -= n; n/4
* n /= 8;
* a -= n; n/32
* etc.
* This will only work if division by a power of 2 is exact.
*/
a = z - ldexp(n, 2); /* 4n */
a -= ldexp( n, 1); /* 2n */
a -= ldexp( n, -2 ); /* n/4 */
a -= ldexp( n, -5 ); /* n/32 */
a -= ldexp( n, -9 ); /* n/512 */
a += ldexp( n, -15 ); /* add n/32768 */
a -= ldexp( n, -17 ); /* n/131072 */
a -= ldexp( n, -18 );
a -= ldexp( n, -20 );
a -= ldexp( n, -22 );
a -= ldexp( n, -24 );
a -= ldexp( n, -28 );
a -= ldexp( n, -32 );
a -= ldexp( n, -37 );
a -= ldexp( n, -39 );
a -= ldexp( n, -40 );
a -= ldexp( n, -42 );
a -= ldexp( n, -46 );
a -= ldexp( n, -47 );
/* Subtract what is left of 2 pi n after all the above reductions.
*/
a -= 2.44929359829470635445e-16 * n;
/* If the test is extended too far, it is possible
* to have chosen the wrong value of n. The following
* will fix that, but at some reduction in accuracy.
*/
if( (a > TPI) || (a < -1e-11) )
{
z = a;
lflg += 1;
printf( "Warning! Reduction failed on first try.\n" );
goto inlup;
}
if( a < 0.0 )
{
printf( "Warning! Reduced value < 0\n" );
a += TPI;
}
/* Compute the test function at x and at a = x mod 2 pi.
*/
y = sin(x);
z = sin(a);
printf( "sin(%.15e) error = %.3e\n", x, y-z );
goto loop;
}

View File

@@ -0,0 +1,103 @@
/* mtherr.c
*
* Library common error handling routine
*
*
*
* SYNOPSIS:
*
* char *fctnam;
* int code;
* int mtherr();
*
* mtherr( fctnam, code );
*
*
*
* DESCRIPTION:
*
* This routine may be called to report one of the following
* error conditions (in the include file mconf.h).
*
* Mnemonic Value Significance
*
* DOMAIN 1 argument domain error
* SING 2 function singularity
* OVERFLOW 3 overflow range error
* UNDERFLOW 4 underflow range error
* TLOSS 5 total loss of precision
* PLOSS 6 partial loss of precision
* EDOM 33 Unix domain error code
* ERANGE 34 Unix range error code
*
* The default version of the file prints the function name,
* passed to it by the pointer fctnam, followed by the
* error condition. The display is directed to the standard
* output device. The routine then returns to the calling
* program. Users may wish to modify the program to abort by
* calling exit() under severe error conditions such as domain
* errors.
*
* Since all error conditions pass control to this function,
* the display may be easily changed, eliminated, or directed
* to an error logging device.
*
* SEE ALSO:
*
* mconf.h
*
*/
/*
Cephes Math Library Release 2.0: April, 1987
Copyright 1984, 1987 by Stephen L. Moshier
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
*/
#if 0
#include <stdio.h>
#endif
#include "mconf.h"
int merror = 0;
/* Notice: the order of appearance of the following
* messages is bound to the error codes defined
* in mconf.h.
*/
static char *ermsg[7] = {
"unknown", /* error code 0 */
"domain", /* error code 1 */
"singularity", /* et seq. */
"overflow",
"underflow",
"total loss of precision",
"partial loss of precision"
};
int mtherr( name, code )
char *name;
int code;
{
#if 0
/* Display string passed by calling program,
* which is supposed to be the name of the
* function in which the error occurred:
*/
printf( "\n%s ", name );
/* Set global error message word */
merror = code;
/* Display error message defined
* by the code argument.
*/
if( (code <= 0) || (code >= 7) )
code = 0;
printf( "%s error\n", ermsg[code] );
#endif
/* Return to calling
* program
*/
return( 0 );
}

View File

@@ -0,0 +1,518 @@
/* mtst.c
Consistency tests for math functions.
To get strict rounding rules on a 386 or 68000 computer,
define SETPREC to 1.
With NTRIALS=10000, the following are typical results for
IEEE double precision arithmetic.
Consistency test of math functions.
Max and rms relative errors for 10000 random arguments.
x = cbrt( cube(x) ): max = 0.00E+00 rms = 0.00E+00
x = atan( tan(x) ): max = 2.21E-16 rms = 3.27E-17
x = sin( asin(x) ): max = 2.13E-16 rms = 2.95E-17
x = sqrt( square(x) ): max = 0.00E+00 rms = 0.00E+00
x = log( exp(x) ): max = 1.11E-16 A rms = 4.35E-18 A
x = tanh( atanh(x) ): max = 2.22E-16 rms = 2.43E-17
x = asinh( sinh(x) ): max = 2.05E-16 rms = 3.49E-18
x = acosh( cosh(x) ): max = 1.43E-15 A rms = 1.54E-17 A
x = log10( exp10(x) ): max = 5.55E-17 A rms = 1.27E-18 A
x = pow( pow(x,a),1/a ): max = 7.60E-14 rms = 1.05E-15
x = cos( acos(x) ): max = 2.22E-16 A rms = 6.90E-17 A
*/
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1987, 1988, 2000 by Stephen L. Moshier
*/
#include <stdio.h>
#include <stdlib.h>
#include "mconf.h"
#ifndef NTRIALS
#define NTRIALS 10000
#endif
/* C9X spells lgam lgamma. */
#define GLIBC2 0
#define GLIBC2r1 0
#define SETPREC 1
#define STRTST 0
#define WTRIALS (NTRIALS/5)
#if GLIBC2
double PI = 3.141592653589793238462643;
double PIO2 = 3.141592653589793238462643 * 0.5;
double MAXLOG = 7.09782712893383996732224E2;
#else
extern double PI;
extern double PIO2;
extern double MAXLOG;
#endif
extern double MINLOG;
/*
define MINLOG -170.0
define MAXLOG +170.0
define PI 3.14159265358979323846
define PIO2 1.570796326794896619
*/
#ifdef ANSIPROT
extern double fabs ( double );
extern double sqrt ( double );
extern double cbrt ( double );
extern double exp ( double );
extern double log ( double );
extern double exp10 ( double );
extern double log10 ( double );
extern double tan ( double );
extern double atan ( double );
extern double sin ( double );
extern double asin ( double );
extern double cos ( double );
extern double acos ( double );
extern double pow ( double, double );
extern double tanh ( double );
extern double atanh ( double );
extern double sinh ( double );
extern double asinh ( double x );
extern double cosh ( double );
extern double acosh ( double );
extern double gamma ( double );
extern double lgam ( double );
extern double jn ( int, double );
extern double yn ( int, double );
extern double ndtr ( double );
extern double ndtri ( double );
extern double stdtr ( int, double );
extern double stdtri ( int, double );
extern double ellpe ( double );
extern double ellpk ( double );
#else
double fabs(), sqrt(), cbrt(), exp(), log();
double exp10(), log10(), tan(), atan();
double sin(), asin(), cos(), acos(), pow();
double tanh(), atanh(), sinh(), asinh(), cosh(), acosh();
double gamma(), lgam(), jn(), yn(), ndtrl(), ndtril();
double stdtrl(), stdtril(), ellpel(), ellpkl();
#endif
#if GLIBC2
extern double lgamma (double);
extern double tgamma ( double );
#endif
#if SETPREC
int dprec();
#endif
int drand();
/* void exit(); */
/* int printf(); */
/* Provide inverses for square root and cube root: */
double square(x)
double x;
{
return( x * x );
}
double cube(x)
double x;
{
return( x * x * x );
}
/* lookup table for each function */
struct fundef
{
char *nam1; /* the function */
double (*name )();
char *nam2; /* its inverse */
double (*inv )();
int nargs; /* number of function arguments */
int tstyp; /* type code of the function */
long ctrl; /* relative error flag */
double arg1w; /* width of domain for 1st arg */
double arg1l; /* lower bound domain 1st arg */
long arg1f; /* flags, e.g. integer arg */
double arg2w; /* same info for args 2, 3, 4 */
double arg2l;
long arg2f;
/*
double arg3w;
double arg3l;
long arg3f;
double arg4w;
double arg4l;
long arg4f;
*/
};
/* fundef.ctrl bits: */
#define RELERR 1
/* fundef.tstyp test types: */
#define POWER 1
#define ELLIP 2
#define GAMMA 3
#define WRONK1 4
#define WRONK2 5
#define WRONK3 6
#define STDTR 7
/* fundef.argNf argument flag bits: */
#define INT 2
#define EXPSCAL 4
#if GLIBC2r1
#define NTESTS 12
#else
#if GLIBC2
#define NTESTS 13
#else
#define NTESTS 17
#endif
#endif
struct fundef defs[NTESTS] = {
{" cube", cube, " cbrt", cbrt, 1, 0, 1, 2002.0, -1001.0, 0,
0.0, 0.0, 0},
{" tan", tan, " atan", atan, 1, 0, 1, 0.0, 0.0, 0,
0.0, 0.0, 0},
{" asin", asin, " sin", sin, 1, 0, 1, 2.0, -1.0, 0,
0.0, 0.0, 0},
{"square", square, " sqrt", sqrt, 1, 0, 1, 170.0, -85.0, EXPSCAL,
0.0, 0.0, 0},
{" exp", exp, " log", log, 1, 0, 0, 340.0, -170.0, 0,
0.0, 0.0, 0},
{" atanh", atanh, " tanh", tanh, 1, 0, 1, 2.0, -1.0, 0,
0.0, 0.0, 0},
{" sinh", sinh, " asinh", asinh, 1, 0, 1, 340.0, 0.0, 0,
0.0, 0.0, 0},
{" cosh", cosh, " acosh", acosh, 1, 0, 0, 340.0, 0.0, 0,
0.0, 0.0, 0},
#if !GLIBC2r1
{" exp10", exp10, " log10", log10, 1, 0, 0, 340.0, -170.0, 0,
0.0, 0.0, 0},
#endif
{"pow", pow, "pow", pow, 2, POWER, 1, 21.0, 0.0, 0,
42.0, -21.0, 0},
{" acos", acos, " cos", cos, 1, 0, 0, 2.0, -1.0, 0,
0.0, 0.0, 0},
#if GLIBC2
#if !GLIBC2r1
{ "tgamma", tgamma, "lgamma", lgamma, 1, GAMMA, 0, 34.0, 0.0, 0,
0.0, 0.0, 0},
#endif
#else
{ "gamma", gamma, "lgam", lgam, 1, GAMMA, 0, 34.0, 0.0, 0,
0.0, 0.0, 0},
#endif
{ " Jn", jn, " Yn", yn, 2, WRONK1, 0, 30.0, 0.1, 0,
40.0, -20.0, INT},
#if !GLIBC2
{ " ndtr", ndtr, " ndtri", ndtri, 1, 0, 1, 10.0L, -10.0L, 0,
0.0, 0.0, 0},
{ " ndtri", ndtri, " ndtr", ndtr, 1, 0, 1, 1.0L, 0.0L, 0,
0.0, 0.0, 0},
{" ellpe", ellpe, " ellpk", ellpk, 1, ELLIP, 0, 1.0L, 0.0L, 0,
0.0, 0.0, 0},
{ "stdtr", stdtr, "stdtri", stdtri, 2, STDTR, 1, 4.0L, -2.0L, 0,
30.0, 1.0, INT},
#endif
};
static char *headrs[] = {
"x = %s( %s(x) ): ",
"x = %s( %s(x,a),1/a ): ", /* power */
"Legendre %s, %s: ", /* ellip */
"%s(x) = log(%s(x)): ", /* gamma */
"Wronksian of %s, %s: ",
"Wronksian of %s, %s: ",
"Wronksian of %s, %s: ",
"x = %s(%s(k,x) ): ", /* stdtr */
};
const static double yy1 = 0.0;
const static double y2 = 0.0;
const static double y3 = 0.0;
const static double y4 = 0.0;
const static double a = 0.0;
const static double x = 0.0;
const static double y = 0.0;
const static double z = 0.0;
const static double e = 0.0;
const static double max = 0.0;
const static double rmsa = 0.0;
const static double rms = 0.0;
const static double ave = 0.0;
int main()
{
double (*fun )();
double (*ifun )();
struct fundef *d;
int i, k, itst;
int m, ntr;
#if SETPREC
dprec(); /* set coprocessor precision */
#endif
ntr = NTRIALS;
printf( "Consistency test of math functions.\n" );
printf( "Max and rms relative errors for %d random arguments.\n",
ntr );
/* Initialize machine dependent parameters: */
defs[1].arg1w = PI;
defs[1].arg1l = -PI/2.0;
/* Microsoft C has trouble with denormal numbers. */
#if 0
defs[3].arg1w = MAXLOG;
defs[3].arg1l = -MAXLOG/2.0;
defs[4].arg1w = 2*MAXLOG;
defs[4].arg1l = -MAXLOG;
#endif
defs[6].arg1w = 2.0*MAXLOG;
defs[6].arg1l = -MAXLOG;
defs[7].arg1w = MAXLOG;
defs[7].arg1l = 0.0;
/* Outer loop, on the test number: */
for( itst=STRTST; itst<NTESTS; itst++ )
{
d = &defs[itst];
k = 0;
m = 0;
max = 0.0;
rmsa = 0.0;
ave = 0.0;
fun = d->name;
ifun = d->inv;
/* Absolute error criterion starts with gamma function
* (put all such at end of table)
*/
#if 0
if( d->tstyp == GAMMA )
printf( "Absolute error criterion (but relative if >1):\n" );
#endif
/* Smaller number of trials for Wronksians
* (put them at end of list)
*/
#if 0
if( d->tstyp == WRONK1 )
{
ntr = WTRIALS;
printf( "Absolute error and only %d trials:\n", ntr );
}
#endif
if( d->tstyp == STDTR )
{
ntr = NTRIALS/10;
printf( "Relative error and only %d trials:\n", ntr );
}
printf( headrs[d->tstyp], d->nam2, d->nam1 );
for( i=0; i<ntr; i++ )
{
m++;
/* make random number(s) in desired range(s) */
switch( d->nargs )
{
default:
goto illegn;
case 2:
drand( &a );
a = d->arg2w * ( a - 1.0 ) + d->arg2l;
if( d->arg2f & EXPSCAL )
{
a = exp(a);
drand( &y2 );
a -= 1.0e-13 * a * y2;
}
if( d->arg2f & INT )
{
k = a + 0.25;
a = k;
}
case 1:
drand( &x );
x = d->arg1w * ( x - 1.0 ) + d->arg1l;
if( d->arg1f & EXPSCAL )
{
x = exp(x);
drand( &a );
x += 1.0e-13 * x * a;
}
}
/* compute function under test */
switch( d->nargs )
{
case 1:
switch( d->tstyp )
{
case ELLIP:
yy1 = ( *(fun) )(x);
y2 = ( *(fun) )(1.0-x);
y3 = ( *(ifun) )(x);
y4 = ( *(ifun) )(1.0-x);
break;
case GAMMA:
#if GLIBC2
y = lgamma(x);
x = log( tgamma(x) );
#else
y = lgam(x);
x = log( gamma(x) );
#endif
break;
default:
z = ( *(fun) )(x);
y = ( *(ifun) )(z);
}
break;
case 2:
if( d->arg2f & INT )
{
switch( d->tstyp )
{
case WRONK1:
yy1 = (*fun)( k, x ); /* jn */
y2 = (*fun)( k+1, x );
y3 = (*ifun)( k, x ); /* yn */
y4 = (*ifun)( k+1, x );
break;
case WRONK2:
yy1 = (*fun)( a, x ); /* iv */
y2 = (*fun)( a+1.0, x );
y3 = (*ifun)( k, x ); /* kn */
y4 = (*ifun)( k+1, x );
break;
default:
z = (*fun)( k, x );
y = (*ifun)( k, z );
}
}
else
{
if( d->tstyp == POWER )
{
z = (*fun)( x, a );
y = (*ifun)( z, 1.0/a );
}
else
{
z = (*fun)( a, x );
y = (*ifun)( a, z );
}
}
break;
default:
illegn:
printf( "Illegal nargs= %d", d->nargs );
exit(1);
}
switch( d->tstyp )
{
case WRONK1:
e = (y2*y3 - yy1*y4) - 2.0/(PI*x); /* Jn, Yn */
break;
case WRONK2:
e = (y2*y3 + yy1*y4) - 1.0/x; /* In, Kn */
break;
case ELLIP:
e = (yy1-y3)*y4 + y3*y2 - PIO2;
break;
default:
e = y - x;
break;
}
if( d->ctrl & RELERR )
e /= x;
else
{
if( fabs(x) > 1.0 )
e /= x;
}
ave += e;
/* absolute value of error */
if( e < 0 )
e = -e;
/* peak detect the error */
if( e > max )
{
max = e;
if( e > 1.0e-10 )
{
printf("x %.6E z %.6E y %.6E max %.4E\n",
x, z, y, max);
if( d->tstyp == POWER )
{
printf( "a %.6E\n", a );
}
if( d->tstyp >= WRONK1 )
{
printf( "yy1 %.4E y2 %.4E y3 %.4E y4 %.4E k %d x %.4E\n",
yy1, y2, y3, y4, k, x );
}
}
/*
printf("%.8E %.8E %.4E %6ld \n", x, y, max, n);
printf("%d %.8E %.8E %.4E %6ld \n", k, x, y, max, n);
printf("%.6E %.6E %.6E %.4E %6ld \n", a, x, y, max, n);
printf("%.6E %.6E %.6E %.6E %.4E %6ld \n", a, b, x, y, max, n);
printf("%.4E %.4E %.4E %.4E %.4E %.4E %6ld \n",
a, b, c, x, y, max, n);
*/
}
/* accumulate rms error */
e *= 1.0e16; /* adjust range */
rmsa += e * e; /* accumulate the square of the error */
}
/* report after NTRIALS trials */
rms = 1.0e-16 * sqrt( rmsa/m );
if(d->ctrl & RELERR)
printf(" max = %.2E rms = %.2E\n", max, rms );
else
printf(" max = %.2E A rms = %.2E A\n", max, rms );
} /* loop on itst */
exit(0);
}

View File

@@ -0,0 +1,30 @@
acosh.obj,-
asin.obj,-
asinh.obj,-
atan.obj,-
atanh.obj,-
cbrt.obj,-
chbevl.obj,-
const.obj,-
cosh.obj,-
drand.obj,-
exp.obj,-
exp10.obj,-
fabs.obj,-
floor.obj,-
log.obj,-
log10.obj,-
polevl.obj,-
pow.obj,-
powi.obj,-
round.obj,-
sin.obj,-
sinh.obj,-
tan.obj,-
tanh.obj,-
unity.obj,-
sqrt.obj,-
floor.obj,-
polevl.obj,-
mtherr.obj,-
sys$library:vaxcrtl/lib

View File

@@ -0,0 +1,116 @@
; Static Name Aliases
;
TITLE polevl
_TEXT SEGMENT BYTE PUBLIC 'CODE'
_TEXT ENDS
CONST SEGMENT WORD PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT WORD PUBLIC 'BSS'
_BSS ENDS
_DATA SEGMENT WORD PUBLIC 'DATA'
_DATA ENDS
DGROUP GROUP CONST, _BSS, _DATA
ASSUME CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
PUBLIC _polevl
PUBLIC _p1evl
_DATA SEGMENT
EXTRN __chkstk:NEAR
EXTRN __fac:NEAR
EXTRN __fltused:NEAR
$T20001 DQ 0000000000H ; .0000000000000000
ans DQ 0
ctrlw DW 0
_DATA ENDS
_TEXT SEGMENT
PUBLIC _polevl
_polevl PROC NEAR
push bp
mov bp,sp
mov ax,12
call __chkstk
push si
mov si,[bp+12]
; fstcw ctrlw
; fwait
; mov ax,ctrlw
; or ax,00100h
; mov ctrlw,ax
; fldcw ctrlw
fldz
fwait
mov ax,[bp+14]
inc ax
mov [bp-12],ax
$D15:
fmul QWORD PTR [bp+4]
add si,8
fwait
fadd QWORD PTR [si-8]
fwait
dec WORD PTR [bp-12]
jne $D15
fstp ans
; fstcw ctrlw
; fwait
; mov ax,ctrlw
; and ax,0feffh
; mov ctrlw,ax
; fldcw ctrlw
lea ax, ans
fwait
pop si
mov sp,bp
pop bp
ret
_polevl ENDP
PUBLIC _p1evl
_p1evl PROC NEAR
push bp
mov bp,sp
mov ax,12
call __chkstk
push si
; fstcw ctrlw
; fwait
; mov ax,ctrlw
; or ax,00100h
; mov ctrlw,ax
; fldcw ctrlw
mov si,[bp+12]
fld QWORD PTR [bp+4]
add si,8
fadd QWORD PTR [si-8]
fwait
mov ax,[bp+14]
dec ax
mov [bp-12],ax
$D26:
fmul QWORD PTR [bp+4]
add si,8
fadd QWORD PTR [si-8]
fwait
dec WORD PTR [bp-12]
jne $D26
fstp ans
lea ax, ans
; fstcw ctrlw
; fwait
; mov ax,ctrlw
; and ax,0feffh
; mov ctrlw,ax
; fldcw ctrlw
fwait
pop si
mov sp,bp
pop bp
ret
_p1evl ENDP
_TEXT ENDS
END

View File

@@ -0,0 +1,97 @@
/* polevl.c
* p1evl.c
*
* Evaluate polynomial
*
*
*
* SYNOPSIS:
*
* int N;
* double x, y, coef[N+1], polevl[];
*
* y = polevl( x, coef, N );
*
*
*
* DESCRIPTION:
*
* Evaluates polynomial of degree N:
*
* 2 N
* y = C + C x + C x +...+ C x
* 0 1 2 N
*
* Coefficients are stored in reverse order:
*
* coef[0] = C , ..., coef[N] = C .
* N 0
*
* The function p1evl() assumes that coef[N] = 1.0 and is
* omitted from the array. Its calling arguments are
* otherwise the same as polevl().
*
*
* SPEED:
*
* In the interest of speed, there are no checks for out
* of bounds arithmetic. This routine is used by most of
* the functions in the library. Depending on available
* equipment features, the user may wish to rewrite the
* program in microcode or assembly language.
*
*/
/*
Cephes Math Library Release 2.1: December, 1988
Copyright 1984, 1987, 1988 by Stephen L. Moshier
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
*/
double polevl( x, coef, N )
double x;
double coef[];
int N;
{
double ans;
int i;
double *p;
p = coef;
ans = *p++;
i = N;
do
ans = ans * x + *p++;
while( --i );
return( ans );
}
/* p1evl() */
/* N
* Evaluate polynomial when coefficient of x is 1.0.
* Otherwise same as polevl.
*/
double p1evl( x, coef, N )
double x;
double coef[];
int N;
{
double ans;
double *p;
int i;
p = coef;
ans = x + *p++;
i = N-1;
do
ans = ans * x + *p++;
while( --i );
return( ans );
}

View File

@@ -0,0 +1,756 @@
/* pow.c
*
* Power function
*
*
*
* SYNOPSIS:
*
* double x, y, z, pow();
*
* z = pow( x, y );
*
*
*
* DESCRIPTION:
*
* Computes x raised to the yth power. Analytically,
*
* x**y = exp( y log(x) ).
*
* Following Cody and Waite, this program uses a lookup table
* of 2**-i/16 and pseudo extended precision arithmetic to
* obtain an extra three bits of accuracy in both the logarithm
* and the exponential.
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* IEEE -26,26 30000 4.2e-16 7.7e-17
* DEC -26,26 60000 4.8e-17 9.1e-18
* 1/26 < x < 26, with log(x) uniformly distributed.
* -26 < y < 26, y uniformly distributed.
* IEEE 0,8700 30000 1.5e-14 2.1e-15
* 0.99 < x < 1.01, 0 < y < 8700, uniformly distributed.
*
*
* ERROR MESSAGES:
*
* message condition value returned
* pow overflow x**y > MAXNUM INFINITY
* pow underflow x**y < 1/MAXNUM 0.0
* pow domain x<0 and y noninteger 0.0
*
*/
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
static char fname[] = {"pow"};
#define SQRTH 0.70710678118654752440
#ifdef UNK
const static double P[] = {
4.97778295871696322025E-1,
3.73336776063286838734E0,
7.69994162726912503298E0,
4.66651806774358464979E0
};
const static double Q[] = {
/* 1.00000000000000000000E0, */
9.33340916416696166113E0,
2.79999886606328401649E1,
3.35994905342304405431E1,
1.39995542032307539578E1
};
/* 2^(-i/16), IEEE precision */
const static double A[] = {
1.00000000000000000000E0,
9.57603280698573700036E-1,
9.17004043204671215328E-1,
8.78126080186649726755E-1,
8.40896415253714502036E-1,
8.05245165974627141736E-1,
7.71105412703970372057E-1,
7.38413072969749673113E-1,
7.07106781186547572737E-1,
6.77127773468446325644E-1,
6.48419777325504820276E-1,
6.20928906036742001007E-1,
5.94603557501360513449E-1,
5.69394317378345782288E-1,
5.45253866332628844837E-1,
5.22136891213706877402E-1,
5.00000000000000000000E-1
};
const static double B[] = {
0.00000000000000000000E0,
1.64155361212281360176E-17,
4.09950501029074826006E-17,
3.97491740484881042808E-17,
-4.83364665672645672553E-17,
1.26912513974441574796E-17,
1.99100761573282305549E-17,
-1.52339103990623557348E-17,
0.00000000000000000000E0
};
const static double R[] = {
1.49664108433729301083E-5,
1.54010762792771901396E-4,
1.33335476964097721140E-3,
9.61812908476554225149E-3,
5.55041086645832347466E-2,
2.40226506959099779976E-1,
6.93147180559945308821E-1
};
#define douba(k) A[k]
#define doubb(k) B[k]
#define MEXP 16383.0
#ifdef DENORMAL
#define MNEXP -17183.0
#else
#define MNEXP -16383.0
#endif
#endif
#ifdef DEC
static unsigned short P[] = {
0037776,0156313,0175332,0163602,
0040556,0167577,0052366,0174245,
0040766,0062753,0175707,0055564,
0040625,0052035,0131344,0155636,
};
static unsigned short Q[] = {
/*0040200,0000000,0000000,0000000,*/
0041025,0052644,0154404,0105155,
0041337,0177772,0007016,0047646,
0041406,0062740,0154273,0020020,
0041137,0177054,0106127,0044555,
};
static unsigned short A[] = {
0040200,0000000,0000000,0000000,
0040165,0022575,0012444,0103314,
0040152,0140306,0163735,0022071,
0040140,0146336,0166052,0112341,
0040127,0042374,0145326,0116553,
0040116,0022214,0012437,0102201,
0040105,0063452,0010525,0003333,
0040075,0004243,0117530,0006067,
0040065,0002363,0031771,0157145,
0040055,0054076,0165102,0120513,
0040045,0177326,0124661,0050471,
0040036,0172462,0060221,0120422,
0040030,0033760,0050615,0134251,
0040021,0141723,0071653,0010703,
0040013,0112701,0161752,0105727,
0040005,0125303,0063714,0044173,
0040000,0000000,0000000,0000000
};
static unsigned short B[] = {
0000000,0000000,0000000,0000000,
0021473,0040265,0153315,0140671,
0121074,0062627,0042146,0176454,
0121413,0003524,0136332,0066212,
0121767,0046404,0166231,0012553,
0121257,0015024,0002357,0043574,
0021736,0106532,0043060,0056206,
0121310,0020334,0165705,0035326,
0000000,0000000,0000000,0000000
};
static unsigned short R[] = {
0034173,0014076,0137624,0115771,
0035041,0076763,0003744,0111311,
0035656,0141766,0041127,0074351,
0036435,0112533,0073611,0116664,
0037143,0054106,0134040,0152223,
0037565,0176757,0176026,0025551,
0040061,0071027,0173721,0147572
};
/*
const static double R[] = {
0.14928852680595608186e-4,
0.15400290440989764601e-3,
0.13333541313585784703e-2,
0.96181290595172416964e-2,
0.55504108664085595326e-1,
0.24022650695909537056e0,
0.69314718055994529629e0
};
*/
#define douba(k) (*(double *)&A[(k)<<2])
#define doubb(k) (*(double *)&B[(k)<<2])
#define MEXP 2031.0
#define MNEXP -2031.0
#endif
#ifdef IBMPC
static unsigned short P[] = {
0x5cf0,0x7f5b,0xdb99,0x3fdf,
0xdf15,0xea9e,0xddef,0x400d,
0xeb6f,0x7f78,0xccbd,0x401e,
0x9b74,0xb65c,0xaa83,0x4012,
};
static unsigned short Q[] = {
/*0x0000,0x0000,0x0000,0x3ff0,*/
0x914e,0x9b20,0xaab4,0x4022,
0xc9f5,0x41c1,0xffff,0x403b,
0x6402,0x1b17,0xccbc,0x4040,
0xe92e,0x918a,0xffc5,0x402b,
};
static unsigned short A[] = {
0x0000,0x0000,0x0000,0x3ff0,
0x90da,0xa2a4,0xa4af,0x3fee,
0xa487,0xdcfb,0x5818,0x3fed,
0x529c,0xdd85,0x199b,0x3fec,
0xd3ad,0x995a,0xe89f,0x3fea,
0xf090,0x82a3,0xc491,0x3fe9,
0xa0db,0x422a,0xace5,0x3fe8,
0x0187,0x73eb,0xa114,0x3fe7,
0x3bcd,0x667f,0xa09e,0x3fe6,
0x5429,0xdd48,0xab07,0x3fe5,
0x2a27,0xd536,0xbfda,0x3fe4,
0x3422,0x4c12,0xdea6,0x3fe3,
0xb715,0x0a31,0x06fe,0x3fe3,
0x6238,0x6e75,0x387a,0x3fe2,
0x517b,0x3c7d,0x72b8,0x3fe1,
0x890f,0x6cf9,0xb558,0x3fe0,
0x0000,0x0000,0x0000,0x3fe0
};
static unsigned short B[] = {
0x0000,0x0000,0x0000,0x0000,
0x3707,0xd75b,0xed02,0x3c72,
0xcc81,0x345d,0xa1cd,0x3c87,
0x4b27,0x5686,0xe9f1,0x3c86,
0x6456,0x13b2,0xdd34,0xbc8b,
0x42e2,0xafec,0x4397,0x3c6d,
0x82e4,0xd231,0xf46a,0x3c76,
0x8a76,0xb9d7,0x9041,0xbc71,
0x0000,0x0000,0x0000,0x0000
};
static unsigned short R[] = {
0x937f,0xd7f2,0x6307,0x3eef,
0x9259,0x60fc,0x2fbe,0x3f24,
0xef1d,0xc84a,0xd87e,0x3f55,
0x33b7,0x6ef1,0xb2ab,0x3f83,
0x1a92,0xd704,0x6b08,0x3fac,
0xc56d,0xff82,0xbfbd,0x3fce,
0x39ef,0xfefa,0x2e42,0x3fe6
};
#define douba(k) (*(double *)&A[(k)<<2])
#define doubb(k) (*(double *)&B[(k)<<2])
#define MEXP 16383.0
#ifdef DENORMAL
#define MNEXP -17183.0
#else
#define MNEXP -16383.0
#endif
#endif
#ifdef MIEEE
static unsigned short P[] = {
0x3fdf,0xdb99,0x7f5b,0x5cf0,
0x400d,0xddef,0xea9e,0xdf15,
0x401e,0xccbd,0x7f78,0xeb6f,
0x4012,0xaa83,0xb65c,0x9b74
};
static unsigned short Q[] = {
0x4022,0xaab4,0x9b20,0x914e,
0x403b,0xffff,0x41c1,0xc9f5,
0x4040,0xccbc,0x1b17,0x6402,
0x402b,0xffc5,0x918a,0xe92e
};
static unsigned short A[] = {
0x3ff0,0x0000,0x0000,0x0000,
0x3fee,0xa4af,0xa2a4,0x90da,
0x3fed,0x5818,0xdcfb,0xa487,
0x3fec,0x199b,0xdd85,0x529c,
0x3fea,0xe89f,0x995a,0xd3ad,
0x3fe9,0xc491,0x82a3,0xf090,
0x3fe8,0xace5,0x422a,0xa0db,
0x3fe7,0xa114,0x73eb,0x0187,
0x3fe6,0xa09e,0x667f,0x3bcd,
0x3fe5,0xab07,0xdd48,0x5429,
0x3fe4,0xbfda,0xd536,0x2a27,
0x3fe3,0xdea6,0x4c12,0x3422,
0x3fe3,0x06fe,0x0a31,0xb715,
0x3fe2,0x387a,0x6e75,0x6238,
0x3fe1,0x72b8,0x3c7d,0x517b,
0x3fe0,0xb558,0x6cf9,0x890f,
0x3fe0,0x0000,0x0000,0x0000
};
static unsigned short B[] = {
0x0000,0x0000,0x0000,0x0000,
0x3c72,0xed02,0xd75b,0x3707,
0x3c87,0xa1cd,0x345d,0xcc81,
0x3c86,0xe9f1,0x5686,0x4b27,
0xbc8b,0xdd34,0x13b2,0x6456,
0x3c6d,0x4397,0xafec,0x42e2,
0x3c76,0xf46a,0xd231,0x82e4,
0xbc71,0x9041,0xb9d7,0x8a76,
0x0000,0x0000,0x0000,0x0000
};
static unsigned short R[] = {
0x3eef,0x6307,0xd7f2,0x937f,
0x3f24,0x2fbe,0x60fc,0x9259,
0x3f55,0xd87e,0xc84a,0xef1d,
0x3f83,0xb2ab,0x6ef1,0x33b7,
0x3fac,0x6b08,0xd704,0x1a92,
0x3fce,0xbfbd,0xff82,0xc56d,
0x3fe6,0x2e42,0xfefa,0x39ef
};
#define douba(k) (*(double *)&A[(k)<<2])
#define doubb(k) (*(double *)&B[(k)<<2])
#define MEXP 16383.0
#ifdef DENORMAL
#define MNEXP -17183.0
#else
#define MNEXP -16383.0
#endif
#endif
/* log2(e) - 1 */
#define LOG2EA 0.44269504088896340736
#define F W
#define Fa Wa
#define Fb Wb
#define G W
#define Ga Wa
#define Gb u
#define H W
#define Ha Wb
#define Hb Wb
#ifdef ANSIPROT
extern double floor ( double );
extern double fabs ( double );
extern double frexp ( double, int * );
extern double ldexp ( double, int );
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
extern double powi ( double, int );
extern int signbit ( double );
extern int isnan ( double );
extern int isfinite ( double );
const static double reduc ( double );
#else
double floor(), fabs(), frexp(), ldexp();
double polevl(), p1evl(), powi();
int signbit(), isnan(), isfinite();
const static double reduc();
#endif
extern double MAXNUM;
#ifdef INFINITIES
extern double INFINITY;
#endif
#ifdef NANS
extern double NAN;
#endif
#ifdef MINUSZERO
extern double NEGZERO;
#endif
double pow( x, y )
double x, y;
{
double w, z, W, Wa, Wb, ya, yb, u;
/* double F, Fa, Fb, G, Ga, Gb, H, Ha, Hb */
double aw, ay, wy;
int e, i, nflg, iyflg, yoddint;
if( y == 0.0 )
return( 1.0 );
#ifdef NANS
if( isnan(x) )
return( x );
if( isnan(y) )
return( y );
#endif
if( y == 1.0 )
return( x );
#ifdef INFINITIES
if( !isfinite(y) && (x == 1.0 || x == -1.0) )
{
mtherr( "pow", DOMAIN );
#ifdef NANS
return( NAN );
#else
return( INFINITY );
#endif
}
#endif
if( x == 1.0 )
return( 1.0 );
if( y >= MAXNUM )
{
#ifdef INFINITIES
if( x > 1.0 )
return( INFINITY );
#else
if( x > 1.0 )
return( MAXNUM );
#endif
if( x > 0.0 && x < 1.0 )
return( 0.0);
if( x < -1.0 )
{
#ifdef INFINITIES
return( INFINITY );
#else
return( MAXNUM );
#endif
}
if( x > -1.0 && x < 0.0 )
return( 0.0 );
}
if( y <= -MAXNUM )
{
if( x > 1.0 )
return( 0.0 );
#ifdef INFINITIES
if( x > 0.0 && x < 1.0 )
return( INFINITY );
#else
if( x > 0.0 && x < 1.0 )
return( MAXNUM );
#endif
if( x < -1.0 )
return( 0.0 );
#ifdef INFINITIES
if( x > -1.0 && x < 0.0 )
return( INFINITY );
#else
if( x > -1.0 && x < 0.0 )
return( MAXNUM );
#endif
}
if( x >= MAXNUM )
{
#if INFINITIES
if( y > 0.0 )
return( INFINITY );
#else
if( y > 0.0 )
return( MAXNUM );
#endif
return(0.0);
}
/* Set iyflg to 1 if y is an integer. */
iyflg = 0;
w = floor(y);
if( w == y )
iyflg = 1;
/* Test for odd integer y. */
yoddint = 0;
if( iyflg )
{
ya = fabs(y);
ya = floor(0.5 * ya);
yb = 0.5 * fabs(w);
if( ya != yb )
yoddint = 1;
}
if( x <= -MAXNUM )
{
if( y > 0.0 )
{
#ifdef INFINITIES
if( yoddint )
return( -INFINITY );
return( INFINITY );
#else
if( yoddint )
return( -MAXNUM );
return( MAXNUM );
#endif
}
if( y < 0.0 )
{
#ifdef MINUSZERO
if( yoddint )
return( NEGZERO );
#endif
return( 0.0 );
}
}
nflg = 0; /* flag = 1 if x<0 raised to integer power */
if( x <= 0.0 )
{
if( x == 0.0 )
{
if( y < 0.0 )
{
#ifdef MINUSZERO
if( signbit(x) && yoddint )
return( -INFINITY );
#endif
#ifdef INFINITIES
return( INFINITY );
#else
return( MAXNUM );
#endif
}
if( y > 0.0 )
{
#ifdef MINUSZERO
if( signbit(x) && yoddint )
return( NEGZERO );
#endif
return( 0.0 );
}
return( 1.0 );
}
else
{
if( iyflg == 0 )
{ /* noninteger power of negative number */
mtherr( fname, DOMAIN );
#ifdef NANS
return(NAN);
#else
return(0.0L);
#endif
}
nflg = 1;
}
}
/* Integer power of an integer. */
if( iyflg )
{
i = w;
w = floor(x);
if( (w == x) && (fabs(y) < 32768.0) )
{
w = powi( x, (int) y );
return( w );
}
}
if( nflg )
x = fabs(x);
/* For results close to 1, use a series expansion. */
w = x - 1.0;
aw = fabs(w);
ay = fabs(y);
wy = w * y;
ya = fabs(wy);
if((aw <= 1.0e-3 && ay <= 1.0)
|| (ya <= 1.0e-3 && ay >= 1.0))
{
z = (((((w*(y-5.)/720. + 1./120.)*w*(y-4.) + 1./24.)*w*(y-3.)
+ 1./6.)*w*(y-2.) + 0.5)*w*(y-1.) )*wy + wy + 1.;
goto done;
}
/* These are probably too much trouble. */
#if 0
w = y * log(x);
if (aw > 1.0e-3 && fabs(w) < 1.0e-3)
{
z = ((((((
w/7. + 1.)*w/6. + 1.)*w/5. + 1.)*w/4. + 1.)*w/3. + 1.)*w/2. + 1.)*w + 1.;
goto done;
}
if(ya <= 1.0e-3 && aw <= 1.0e-4)
{
z = (((((
wy*1./720.
+ (-w*1./48. + 1./120.) )*wy
+ ((w*17./144. - 1./12.)*w + 1./24.) )*wy
+ (((-w*5./16. + 7./24.)*w - 1./4.)*w + 1./6.) )*wy
+ ((((w*137./360. - 5./12.)*w + 11./24.)*w - 1./2.)*w + 1./2.) )*wy
+ (((((-w*1./6. + 1./5.)*w - 1./4)*w + 1./3.)*w -1./2.)*w ) )*wy
+ wy + 1.0;
goto done;
}
#endif
/* separate significand from exponent */
x = frexp( x, &e );
#if 0
/* For debugging, check for gross overflow. */
if( (e * y) > (MEXP + 1024) )
goto overflow;
#endif
/* Find significand of x in antilog table A[]. */
i = 1;
if( x <= douba(9) )
i = 9;
if( x <= douba(i+4) )
i += 4;
if( x <= douba(i+2) )
i += 2;
if( x >= douba(1) )
i = -1;
i += 1;
/* Find (x - A[i])/A[i]
* in order to compute log(x/A[i]):
*
* log(x) = log( a x/a ) = log(a) + log(x/a)
*
* log(x/a) = log(1+v), v = x/a - 1 = (x-a)/a
*/
x -= douba(i);
x -= doubb(i/2);
x /= douba(i);
/* rational approximation for log(1+v):
*
* log(1+v) = v - v**2/2 + v**3 P(v) / Q(v)
*/
z = x*x;
w = x * ( z * polevl( x, P, 3 ) / p1evl( x, Q, 4 ) );
w = w - ldexp( z, -1 ); /* w - 0.5 * z */
/* Convert to base 2 logarithm:
* multiply by log2(e)
*/
w = w + LOG2EA * w;
/* Note x was not yet added in
* to above rational approximation,
* so do it now, while multiplying
* by log2(e).
*/
z = w + LOG2EA * x;
z = z + x;
/* Compute exponent term of the base 2 logarithm. */
w = -i;
w = ldexp( w, -4 ); /* divide by 16 */
w += e;
/* Now base 2 log of x is w + z. */
/* Multiply base 2 log by y, in extended precision. */
/* separate y into large part ya
* and small part yb less than 1/16
*/
ya = reduc(y);
yb = y - ya;
F = z * y + w * yb;
Fa = reduc(F);
Fb = F - Fa;
G = Fa + w * ya;
Ga = reduc(G);
Gb = G - Ga;
H = Fb + Gb;
Ha = reduc(H);
w = ldexp( Ga+Ha, 4 );
/* Test the power of 2 for overflow */
if( w > MEXP )
{
#ifndef INFINITIES
mtherr( fname, OVERFLOW );
#endif
#ifdef INFINITIES
if( nflg && yoddint )
return( -INFINITY );
return( INFINITY );
#else
if( nflg && yoddint )
return( -MAXNUM );
return( MAXNUM );
#endif
}
if( w < (MNEXP - 1) )
{
#ifndef DENORMAL
mtherr( fname, UNDERFLOW );
#endif
#ifdef MINUSZERO
if( nflg && yoddint )
return( NEGZERO );
#endif
return( 0.0 );
}
e = w;
Hb = H - Ha;
if( Hb > 0.0 )
{
e += 1;
Hb -= 0.0625;
}
/* Now the product y * log2(x) = Hb + e/16.0.
*
* Compute base 2 exponential of Hb,
* where -0.0625 <= Hb <= 0.
*/
z = Hb * polevl( Hb, R, 6 ); /* z = 2**Hb - 1 */
/* Express e/16 as an integer plus a negative number of 16ths.
* Find lookup table entry for the fractional power of 2.
*/
if( e < 0 )
i = 0;
else
i = 1;
i = e/16 + i;
e = 16*i - e;
w = douba( e );
z = w + w * z; /* 2**-e * ( 1 + (2**Hb-1) ) */
z = ldexp( z, i ); /* multiply by integer power of 2 */
done:
/* Negate if odd integer power of negative number */
if( nflg && yoddint )
{
#ifdef MINUSZERO
if( z == 0.0 )
z = NEGZERO;
else
#endif
z = -z;
}
return( z );
}
/* Find a multiple of 1/16 that is within 1/16 of x. */
const static double reduc(x)
double x;
{
double t;
t = ldexp( x, 4 );
t = floor( t );
t = ldexp( t, -4 );
return(t);
}

View File

@@ -0,0 +1,186 @@
/* powi.c
*
* Real raised to integer power
*
*
*
* SYNOPSIS:
*
* double x, y, powi();
* int n;
*
* y = powi( x, n );
*
*
*
* DESCRIPTION:
*
* Returns argument x raised to the nth power.
* The routine efficiently decomposes n as a sum of powers of
* two. The desired power is a product of two-to-the-kth
* powers of x. Thus to compute the 32767 power of x requires
* 28 multiplications instead of 32767 multiplications.
*
*
*
* ACCURACY:
*
*
* Relative error:
* arithmetic x domain n domain # trials peak rms
* DEC .04,26 -26,26 100000 2.7e-16 4.3e-17
* IEEE .04,26 -26,26 50000 2.0e-15 3.8e-16
* IEEE 1,2 -1022,1023 50000 8.6e-14 1.6e-14
*
* Returns MAXNUM on overflow, zero on underflow.
*
*/
/* powi.c */
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
#ifdef ANSIPROT
extern double log ( double );
extern double frexp ( double, int * );
extern int signbit ( double );
#else
double log(), frexp();
int signbit();
#endif
extern double NEGZERO, INFINITY, MAXNUM, MAXLOG, MINLOG, LOGE2;
double powi( x, nn )
double x;
int nn;
{
int n, e, sign, asign, lx;
double w, y, s;
/* See pow.c for these tests. */
if( x == 0.0 )
{
if( nn == 0 )
return( 1.0 );
else if( nn < 0 )
return( INFINITY );
else
{
if( nn & 1 )
return( x );
else
return( 0.0 );
}
}
if( nn == 0 )
return( 1.0 );
if( nn == -1 )
return( 1.0/x );
if( x < 0.0 )
{
asign = -1;
x = -x;
}
else
asign = 0;
if( nn < 0 )
{
sign = -1;
n = -nn;
}
else
{
sign = 1;
n = nn;
}
/* Even power will be positive. */
if( (n & 1) == 0 )
asign = 0;
/* Overflow detection */
/* Calculate approximate logarithm of answer */
s = frexp( x, &lx );
e = (lx - 1)*n;
if( (e == 0) || (e > 64) || (e < -64) )
{
s = (s - 7.0710678118654752e-1) / (s + 7.0710678118654752e-1);
s = (2.9142135623730950 * s - 0.5 + lx) * nn * LOGE2;
}
else
{
s = LOGE2 * e;
}
if( s > MAXLOG )
{
mtherr( "powi", OVERFLOW );
y = INFINITY;
goto done;
}
#if DENORMAL
if( s < MINLOG )
{
y = 0.0;
goto done;
}
/* Handle tiny denormal answer, but with less accuracy
* since roundoff error in 1.0/x will be amplified.
* The precise demarcation should be the gradual underflow threshold.
*/
if( (s < (-MAXLOG+2.0)) && (sign < 0) )
{
x = 1.0/x;
sign = -sign;
}
#else
/* do not produce denormal answer */
if( s < -MAXLOG )
return(0.0);
#endif
/* First bit of the power */
if( n & 1 )
y = x;
else
y = 1.0;
w = x;
n >>= 1;
while( n )
{
w = w * w; /* arg to the 2-to-the-kth power */
if( n & 1 ) /* if that bit is set, then include in product */
y *= w;
n >>= 1;
}
if( sign < 0 )
y = 1.0/y;
done:
if( asign )
{
/* odd power of negative number */
if( y == 0.0 )
y = NEGZERO;
else
y = -y;
}
return(y);
}

View File

@@ -0,0 +1,184 @@
/*
* This file was automatically generated by version 1.7 of cextract.
* Manual editing not recommended.
*
* Created: Fri Mar 31 19:17:33 1995
*/
extern double acosh ( double x );
extern int airy ( double, double *, double *, double *, double * );
extern double asin ( double );
extern double acos ( double );
extern double asinh ( double x );
extern double atan ( double );
extern double atan2 ( double y, double x );
extern double atanh ( double );
extern double bdtrc ( int k, int n, double p );
extern double bdtr ( int k, int n, double p );
extern double bdtri ( int k, int n, double y );
extern double beta ( double a, double b );
extern double lbeta ( double a, double b );
extern double btdtr ( double a, double b, double x );
extern double cbrt ( double );
extern double chbevl ( double, void *, int );
extern double chdtrc ( double df, double x );
extern double chdtr ( double df, double x );
extern double chdtri ( double df, double y );
//extern void clog ( cmplx *z, cmplx *w );
//extern void cexp ( cmplx *z, cmplx *w );
//extern void csin ( cmplx *z, cmplx *w );
//extern void ccos ( cmplx *z, cmplx *w );
//extern void ctan ( cmplx *z, cmplx *w );
extern void ccot ( cmplx *z, cmplx *w );
//extern void casin ( cmplx *z, cmplx *w );
//extern void cacos ( cmplx *z, cmplx *w );
//extern void catan ( cmplx *z, cmplx *w );
extern void cadd ( cmplx *a, cmplx *b, cmplx *c );
extern void csub ( cmplx *a, cmplx *b, cmplx *c );
extern void cmul ( cmplx *a, cmplx *b, cmplx *c );
extern void cdiv ( cmplx *a, cmplx *b, cmplx *c );
extern void cmov ( void *a, void *b );
extern void cneg ( cmplx *a );
//extern double cabs ( cmplx *z );
//extern void csqrt ( cmplx *z, cmplx *w );
extern double hypot ( double, double );
extern double cosh ( double );
extern double dawsn ( double xx );
extern void eigens ( double A[], double RR[], double E[], int N );
extern double ellie ( double, double );
extern double ellik ( double, double );
extern double ellpe ( double );
extern int ellpj ( double u, double m, double *sn, double *cn, double *dn, double *ph );
extern double ellpk ( double );
extern double exp10 ( double );
extern double exp1m ( double );
extern double exp2 ( double );
extern double expn ( int n, double x );
extern double fac ( int i );
extern double fdtrc ( int ia, int ib, double x );
extern double fdtr ( int ia, int ib, double x );
extern double fdtri ( int ia, int ib, double y );
extern int fftr ( double x[], int m0, double sine[] );
extern double ceil ( double x );
extern double fabs ( double );
extern double floor ( double );
extern double frexp ( double, int * );
extern double ldexp ( double, int );
extern int signbit ( double );
extern int isnan ( double );
extern int isfinite ( double );
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
extern double exp ( double );
extern double log ( double );
extern double sin ( double );
extern double cos ( double );
extern double sqrt ( double );
extern int fresnl ( double xxa, double *ssa, double *cca );
extern double gamma ( double );
extern double lgam ( double );
extern double gdtr ( double a, double b, double x );
extern double gdtrc ( double a, double b, double x );
extern int gels ( double A[], double R[], int M, double EPS, double AUX[] );
extern double hyp2f1 ( double a, double b, double c, double x );
extern double hyperg ( double, double, double );
extern double hyp2f0 ( double a, double b, double x, int type, double *err );
extern double i0 ( double );
extern double i0e ( double x );
extern double i1 ( double );
extern double i1e ( double x );
extern double igamc ( double, double );
extern double igam ( double, double );
extern double igami ( double, double );
extern double incbet ( double, double, double );
extern double incbi ( double, double, double );
extern double iv ( double v, double x );
extern double j0 ( double );
extern double y0 ( double );
extern double j1 ( double );
extern double y1 ( double );
extern double jn ( int n, double x );
extern double jv ( double, double );
extern double k0 ( double x );
extern double k0e ( double x );
extern double k1 ( double x );
extern double k1e ( double x );
extern double kn ( int nn, double x );
extern int levnsn ( int n, double r[], double a[], double e[], double refl[] );
extern double log10 ( double );
extern double log2 ( double );
extern long lrand ( void );
extern long lsqrt ( long x );
extern int minv ( double A[], double X[], int n, double B[], int IPS[] );
extern int mmmpy ( int r, int c, double *A, double *B, double *Y );
extern int mtherr ( char *name, int code );
extern int mtransp ( int n, double *A, double *T );
extern int mvmpy ( int r, int c, double *A, double *V, double *Y );
extern double nbdtrc ( int k, int n, double p );
extern double nbdtr ( int k, int n, double p );
extern double nbdtri ( int k, int n, double p );
extern double ndtr ( double a );
extern double erfc ( double );
extern double erf ( double );
extern double ndtri ( double );
extern double pdtrc ( int k, double m );
extern double pdtr ( int k, double m );
extern double pdtri ( int k, double y );
extern double pow ( double, double );
extern double powi ( double, int );
extern double psi ( double );
extern void revers ( double y[], double x[], int n );
extern double rgamma ( double x );
extern double round ( double );
extern int sprec ( void );
extern int dprec ( void );
extern int ldprec ( void );
extern int shichi ( double x, double *si, double *ci );
extern int sici ( double x, double *si, double *ci );
extern double simpsn ( double f[], double delta );
extern int simq ( double A[], double B[], double X[], int n, int flag, int IPS[] );
extern double radian ( double d, double m, double s );
/*
extern int sincos ( double x, double *s, double *c, int flg );
*/
extern double sindg ( double x );
extern double cosdg ( double x );
extern double sinh ( double );
extern double spence ( double );
extern double stdtr ( int k, double t );
extern double stdtri ( int k, double p );
extern double onef2 ( double a, double b, double c, double x, double *err );
extern double threef0 ( double a, double b, double c, double x, double *err );
extern double struve ( double v, double x );
extern double tan ( double );
extern double cot ( double );
extern double tandg ( double x );
extern double cotdg ( double x );
extern double tanh ( double );
extern double log1p ( double );
extern double exmp1 ( double );
extern double cosm1 ( double x );
extern double yn ( int, double );
extern double zeta ( double x, double q );
extern double zetac ( double );
extern int drand ( double *a );
double smirnov ( int, double );
double smirnovi ( int, double );
double kolmogorov ( double );
double kolmogi ( double );
/* polyn.c */
extern void polini ( int maxdeg );
extern void polprt ( double a[], int na, int d );
extern void polclr ( double *a, int n );
extern void polmov ( double *a, int na, double *b );
extern void polmul ( double a[], int na, double b[], int nb, double c[] );
extern void poladd ( double a[], int na, double b[], int nb, double c[] );
extern void polsub ( double a[], int na, double b[], int nb, double c[] );
extern int poldiv ( double a[], int na, double b[], int nb, double c[] );
extern void polsbt ( double a[], int na, double b[], int nb, double c[] );
extern double poleva ( double a[], int na, double x );
/* polmisc.c */
extern void polatn ( double num[], double den[], double ans[], int nn );
extern void polsqt ( double pol[], double ans[], int nn );
extern void polsin ( double x[], double y[], int nn );
extern void polcos ( double x[], double y[], int nn );

View File

@@ -0,0 +1,70 @@
/* round.c
*
* Round double to nearest or even integer valued double
*
*
*
* SYNOPSIS:
*
* double x, y, round();
*
* y = round(x);
*
*
*
* DESCRIPTION:
*
* Returns the nearest integer to x as a double precision
* floating point result. If x ends in 0.5 exactly, the
* nearest even integer is chosen.
*
*
*
* ACCURACY:
*
* If x is greater than 1/(2*MACHEP), its closest machine
* representation is already an integer, so rounding does
* not change it.
*/
/*
Cephes Math Library Release 2.1: January, 1989
Copyright 1984, 1987, 1989 by Stephen L. Moshier
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
*/
#include "mconf.h"
#ifdef ANSIPROT
double floor ( double );
#else
double floor();
#endif
double round(x)
double x;
{
double y, r;
/* Largest integer <= x */
y = floor(x);
/* Fractional part */
r = x - y;
/* Round up to nearest. */
if( r > 0.5 )
goto rndup;
/* Round to even */
if( r == 0.5 )
{
r = y - 2.0 * floor( 0.5 * y );
if( r == 1.0 )
{
rndup:
y += 1.0;
}
}
/* Else round down. */
return(y);
}

View File

@@ -0,0 +1,207 @@
;
; Borland assembler header
;
; Microsoft MASM subroutines for setting coprocessor precision
;
.286
.287
PREC_TEXT SEGMENT BYTE PUBLIC 'CODE'
PREC_TEXT ENDS
DGROUP group _DATA,_BSS
assume cs:PREC_TEXT,ds:DGROUP
_DATA segment word public 'DATA'
d@ label byte
d@w label word
_DATA ends
_BSS segment word public 'BSS'
b@ label byte
b@w label word
_BSS ends
; exception masks (1 = masked)
; 1 invalid operation
; 2 denormalized operand
; 4 zero divide
; 8 overflow
; 10 underflow
; 20 precision
_DATA SEGMENT
; double precision setting
;;ctlwrd dw 01230h ; note this traps on denormal operands!
;;ctld dw 0133fh ; this doesn't trap
ctld dw 01230h
; single precision
ctls dw 01030h
; long double precision
ctlld dw 01320h
_DATA ENDS
PREC_TEXT segment byte public 'CODE'
assume cs:PREC_TEXT,ds:DGROUP
; Set coprocessor to single precision float
PUBLIC _sprec
_sprec PROC FAR
fclex
fwait
finit
fwait
fldcw word ptr ctls
fwait
ret
_sprec ENDP
; set coprocessor to long double precision
PUBLIC _ldprec
_ldprec PROC far
fclex
fwait
finit
fwait
fldcw word ptr ctlld
fwait
ret
_ldprec ENDP
; set coprocessor to double precision
PUBLIC _dprec
_dprec PROC far
fclex
fwait
finit
fwait
fldcw word ptr ctld
fwait
ret
_dprec ENDP
; get a double promoted to long double size
; getld( &doub, &ldoub );
PUBLIC _getld
_getld PROC far
push bp
mov bp,sp
push bx
mov bx, word ptr [bp+4]
; fld st(0)
fld qword ptr [bx]
mov bx, word ptr [bp+6]
fstp tbyte ptr [bx]
mov bx, word ptr [bp+4]
fld qword ptr [bx]
mov bx, word ptr [bp+8]
fstp qword ptr [bx]
pop bx
pop bp
ret
_getld ENDP
PUBLIC _getprec
_getprec PROC far
push bp
mov bp,sp
sub sp,4
fstcw [bp-4]
fwait
mov ax,[bp-4]
add sp,4
pop bp
ret
_getprec ENDP
PUBLIC _fpclear
_fpclear PROC far
push bp
mov bp,sp
fnclex
fwait
pop bp
ret
_fpclear ENDP
PUBLIC _noexcept
_noexcept PROC far
push bp
mov bp,sp
push ax
sub sp,4
fnclex
fwait
fstcw [bp-4]
fwait
mov ax,[bp-4]
and ax,0FFC0h
or ax,003fh
mov [bp-4],ax
fldcw [bp-4]
add sp,4
pop ax
pop bp
ret
_noexcept ENDP
; single precision square root
; assumes coprocessor precision already set up
; return value in static __fac
PUBLIC _sqrtf
_sqrtf PROC FAR
push bp
mov bp,sp
fld DWORD PTR [bp+6]
fsqrt
fwait
mov sp,bp
pop bp
ret
_sqrtf ENDP
; double precision square root
; assumes coprocessor precision already set up
; return value in static __fac
PUBLIC _sqrt
_sqrt PROC FAR
push bp
mov bp,sp
fld QWORD PTR [bp+6]
fsqrt
fwait
mov sp,bp
pop bp
ret
_sqrt ENDP
; long double precision square root
; assumes coprocessor precision already set up
; return value in fp register
PUBLIC _sqrtl
_sqrtl PROC FAR
push bp
mov bp,sp
fld tbyte ptr [bp+6]
fsqrt
fwait
mov sp,bp
pop bp
ret
_sqrtl ENDP
PREC_TEXT ends
_DATA segment word public 'DATA'
s@ label byte
_DATA ends
PREC_TEXT segment byte public 'CODE'
PREC_TEXT ends
_s@ equ s@
public _sprec
public _dprec
public _ldprec
end

View File

@@ -0,0 +1,87 @@
/* Set 80387 floating point hardware rounding precision */
.file "setprec.387"
.text
.align 2
.globl _sprec
_sprec:
pushl %ebp
movl %esp,%ebp
pushl %eax
subl $4,%esp
fstcw (%esp)
fwait
movl (%esp),%eax
andl $0xfcff,%eax
movl %eax,(%esp)
fldcw (%esp)
popl %eax
popl %eax
leave
ret
.align 2
.globl _dprec
_dprec:
pushl %ebp
movl %esp,%ebp
pushl %eax
subl $4,%esp
fstcw (%esp)
fwait
movl (%esp),%eax
/* andl $0xfcff,%eax */
/* exception on overflow */
andl $0xfcf7,%eax
orl $0x200,%eax
movl %eax,(%esp)
fldcw (%esp)
popl %eax
popl %eax
leave
ret
.align 2
.globl _ldprec
_ldprec:
pushl %ebp
movl %esp,%ebp
pushl %eax
subl $4,%esp
fstcw (%esp)
fwait
movl (%esp),%eax
orl $0x300,%eax
movl %eax,(%esp)
fldcw (%esp)
popl %eax
popl %eax
leave
ret
.globl _getprec
_getprec:
pushl %ebp
movl %esp,%ebp
subl $4,%esp
fstcw (%esp)
fwait
movl (%esp),%eax
leave
ret
.globl _setfpu
_setfpu:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%eax
pushl %eax
fldcw (%esp)
fwait
movl %ebp,%esp
popl %ebp
ret

View File

@@ -0,0 +1,35 @@
/* Set 68881/2 floating point rounding precision */
/* Reference: MC68881/MC68882 Floating-Point Coprocessor */
/* User's Manual, Motorola, Prentice-Hall, 1987 (First Edition) */
/* Pages 1-14, 2-3, 4-68. */
/* FPcr code $80 sets the 68882 coprocessor to */
/* rounding precision = 53 bits */
/* rounding mode = nearest or even */
/* all exceptions (bits 8-15) disabled */
/* The instruction is */
/* FMOVE.L #$80,Fcr */
/* if the assembler will understand it. */
.align 2
.text
/* set to single precision */
.globl _sprec
_sprec
.word 0xf23c,0x9000,0x0000,0x0040
rts
/* set to double precision */
.globl _dprec
_dprec:
.word 0xf23c,0x9000,0x0000,0x0080
rts
/* set to extended (long double) precision */
.globl _ldprec
_ldprec:
.word 0xf23c,0x9000,0x0000,0x0000
rts

View File

@@ -0,0 +1,208 @@
;
; Microsoft MASM subroutines for setting coprocessor precision
;
.286
.287
_TEXT SEGMENT BYTE PUBLIC 'CODE'
_TEXT ENDS
CONST SEGMENT WORD PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT WORD PUBLIC 'BSS'
_BSS ENDS
_DATA SEGMENT WORD PUBLIC 'DATA'
_DATA ENDS
DGROUP GROUP CONST, _BSS, _DATA
ASSUME CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
EXTRN __fac:QWORD
_BSS SEGMENT
EXTRN __fltused:NEAR
_BSS ENDS
; exception masks (1 = masked)
; 1 invalid operation
; 2 denormalized operand
; 4 zero divide
; 8 overflow
; 10 underflow
; 20 precision
_DATA SEGMENT
; double precision setting
;;ctlwrd dw 01230h ; note this traps on denormal operands!
;;ctld dw 0133fh ; this doesn't trap
ctld dw 01230h
; single precision
ctls dw 01030h
; long double precision
ctlld dw 01320h
_DATA ENDS
ASSUME CS: _TEXT
_TEXT SEGMENT
; Set coprocessor to single precision float
PUBLIC _sprec
_sprec PROC NEAR
fclex
fwait
finit
fwait
fldcw word ptr ctls
fwait
ret
_sprec ENDP
; set coprocessor to long double precision
PUBLIC _ldprec
_ldprec PROC NEAR
fclex
fwait
finit
fwait
fldcw word ptr ctlld
fwait
ret
_ldprec ENDP
; set coprocessor to double precision
PUBLIC _dprec
_dprec PROC NEAR
fclex
fwait
finit
fwait
fldcw word ptr ctld
fwait
ret
_dprec ENDP
; get a double promoted to long double size
; getld( &doub, &ldoub );
PUBLIC _getld
_getld PROC NEAR
push bp
mov bp,sp
push bx
mov bx, word ptr [bp+4]
; fld st(0)
fld qword ptr [bx]
mov bx, word ptr [bp+6]
fstp tbyte ptr [bx]
mov bx, word ptr [bp+4]
fld qword ptr [bx]
mov bx, word ptr [bp+8]
fstp qword ptr [bx]
pop bx
pop bp
ret
_getld ENDP
PUBLIC _getprec
_getprec PROC NEAR
push bp
mov bp,sp
sub sp,4
fstcw [bp-4]
fwait
mov ax,[bp-4]
add sp,4
pop bp
ret
_getprec ENDP
PUBLIC _fpclear
_fpclear PROC NEAR
push bp
mov bp,sp
fnclex
fwait
pop bp
ret
_fpclear ENDP
PUBLIC _noexcept
_noexcept PROC NEAR
push bp
mov bp,sp
push ax
sub sp,4
fnclex
fwait
fstcw [bp-4]
fwait
mov ax,[bp-4]
and ax,0FFC0h
or ax,003fh
mov [bp-4],ax
fldcw [bp-4]
add sp,4
pop ax
pop bp
ret
_noexcept ENDP
;; single precision square root
;; assumes coprocessor precision already set up
;; return value in static __fac
; PUBLIC _sqrtf
;_sqrtf PROC NEAR
; push bp
; mov bp,sp
; fld DWORD PTR [bp+4]
; fsqrt
; fwait
; fstp DWORD PTR __fac
; mov ax,OFFSET __fac
; mov sp,bp
; pop bp
; ret
;_sqrtf ENDP
;
;
;; double precision square root
;; assumes coprocessor precision already set up
;; return value in static __fac
; PUBLIC _sqrt
;_sqrt PROC NEAR
; push bp
; mov bp,sp
; fld QWORD PTR [bp+4]
; fsqrt
; fwait
; fstp QWORD PTR __fac
; mov ax,OFFSET __fac
; mov sp,bp
; pop bp
; ret
;_sqrt ENDP
;
;
;; long double precision square root
;; assumes coprocessor precision already set up
;; return value in fp register
; PUBLIC _sqrtl
;_sqrtl PROC NEAR
; push bp
; mov bp,sp
; fld tbyte ptr [bp+4]
; fsqrt
; fwait
; mov sp,bp
; pop bp
; ret
;_sqrtl ENDP
;
_TEXT ENDS
END

View File

@@ -0,0 +1,10 @@
/* Null stubs for coprocessor precision settings */
int
sprec() {return 0; }
int
dprec() {return 0; }
int
ldprec() {return 0; }

View File

@@ -0,0 +1,83 @@
/* Set 80387 floating point hardware rounding precision */
.file "setprec.387"
.version "01.01"
.text
.align 16
.globl sprec
sprec:
pushl %ebp
movl %esp,%ebp
pushl %eax
subl $4,%esp
fstcw (%esp)
fwait
movl (%esp),%eax
andl $0xfcff,%eax
movl %eax,(%esp)
fldcw (%esp)
popl %eax
popl %eax
leave
ret
.Lfe1:
.size sprec,.Lfe1-sprec
.align 16
.globl dprec
dprec:
pushl %ebp
movl %esp,%ebp
pushl %eax
subl $4,%esp
fstcw (%esp)
fwait
movl (%esp),%eax
andl $0xfcff,%eax
/* trap on overflow */
/* andl $0xfcf7,%eax */
orl $0x200,%eax
movl %eax,(%esp)
fldcw (%esp)
popl %eax
popl %eax
leave
ret
.Lfe2:
.size dprec,.Lfe2-dprec
.align 16
.globl ldprec
ldprec:
pushl %ebp
movl %esp,%ebp
pushl %eax
subl $4,%esp
fstcw (%esp)
fwait
movl (%esp),%eax
orl $0x300,%eax
movl %eax,(%esp)
fldcw (%esp)
popl %eax
popl %eax
leave
ret
.Lfe3:
.size ldprec,.Lfe3-ldprec
.align 16
.globl getprec
getprec:
pushl %ebp
movl %esp,%ebp
subl $4,%esp
fstcw (%esp)
fwait
movl (%esp),%eax
leave
ret
.Lfe4:
.size getprec,.Lfe4-getprec

View File

@@ -0,0 +1,387 @@
/* sin.c
*
* Circular sine
*
*
*
* SYNOPSIS:
*
* double x, y, sin();
*
* y = sin( x );
*
*
*
* DESCRIPTION:
*
* Range reduction is into intervals of pi/4. The reduction
* error is nearly eliminated by contriving an extended precision
* modular arithmetic.
*
* Two polynomial approximating functions are employed.
* Between 0 and pi/4 the sine is approximated by
* x + x**3 P(x**2).
* Between pi/4 and pi/2 the cosine is represented as
* 1 - x**2 Q(x**2).
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC 0, 10 150000 3.0e-17 7.8e-18
* IEEE -1.07e9,+1.07e9 130000 2.1e-16 5.4e-17
*
* ERROR MESSAGES:
*
* message condition value returned
* sin total loss x > 1.073741824e9 0.0
*
* Partial loss of accuracy begins to occur at x = 2**30
* = 1.074e9. The loss is not gradual, but jumps suddenly to
* about 1 part in 10e7. Results may be meaningless for
* x > 2**49 = 5.6e14. The routine as implemented flags a
* TLOSS error for x > 2**30 and returns 0.0.
*/
/* cos.c
*
* Circular cosine
*
*
*
* SYNOPSIS:
*
* double x, y, cos();
*
* y = cos( x );
*
*
*
* DESCRIPTION:
*
* Range reduction is into intervals of pi/4. The reduction
* error is nearly eliminated by contriving an extended precision
* modular arithmetic.
*
* Two polynomial approximating functions are employed.
* Between 0 and pi/4 the cosine is approximated by
* 1 - x**2 Q(x**2).
* Between pi/4 and pi/2 the sine is represented as
* x + x**3 P(x**2).
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* IEEE -1.07e9,+1.07e9 130000 2.1e-16 5.4e-17
* DEC 0,+1.07e9 17000 3.0e-17 7.2e-18
*/
/* sin.c */
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1985, 1995, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
#ifdef UNK
const static double sincof[] = {
1.58962301576546568060E-10,
-2.50507477628578072866E-8,
2.75573136213857245213E-6,
-1.98412698295895385996E-4,
8.33333333332211858878E-3,
-1.66666666666666307295E-1,
};
const static double coscof[6] = {
-1.13585365213876817300E-11,
2.08757008419747316778E-9,
-2.75573141792967388112E-7,
2.48015872888517045348E-5,
-1.38888888888730564116E-3,
4.16666666666665929218E-2,
};
const static double DP1 = 7.85398125648498535156E-1;
const static double DP2 = 3.77489470793079817668E-8;
const static double DP3 = 2.69515142907905952645E-15;
/* const static double lossth = 1.073741824e9; */
#endif
#ifdef DEC
static unsigned short sincof[] = {
0030056,0143750,0177214,0163153,
0131727,0027455,0044510,0175352,
0033470,0167432,0131752,0042414,
0135120,0006400,0146776,0174027,
0036410,0104210,0104207,0137202,
0137452,0125252,0125252,0125103,
};
static unsigned short coscof[24] = {
0127107,0151115,0002060,0152325,
0031017,0072353,0155161,0174053,
0132623,0171173,0172542,0057056,
0034320,0006400,0147102,0023652,
0135666,0005540,0133012,0076213,
0037052,0125252,0125252,0125126,
};
/* 7.853981629014015197753906250000E-1 */
static unsigned short P1[] = {0040111,0007732,0120000,0000000,};
/* 4.960467869796758577649598009884E-10 */
static unsigned short P2[] = {0030410,0055060,0100000,0000000,};
/* 2.860594363054915898381331279295E-18 */
static unsigned short P3[] = {0021523,0011431,0105056,0001560,};
#define DP1 *(double *)P1
#define DP2 *(double *)P2
#define DP3 *(double *)P3
#endif
#ifdef IBMPC
static unsigned short sincof[] = {
0x9ccd,0x1fd1,0xd8fd,0x3de5,
0x1f5d,0xa929,0xe5e5,0xbe5a,
0x48a1,0x567d,0x1de3,0x3ec7,
0xdf03,0x19bf,0x01a0,0xbf2a,
0xf7d0,0x1110,0x1111,0x3f81,
0x5548,0x5555,0x5555,0xbfc5,
};
static unsigned short coscof[24] = {
0x1a9b,0xa086,0xfa49,0xbda8,
0x3f05,0x7b4e,0xee9d,0x3e21,
0x4bc6,0x7eac,0x7e4f,0xbe92,
0x44f5,0x19c8,0x01a0,0x3efa,
0x4f91,0x16c1,0xc16c,0xbf56,
0x554b,0x5555,0x5555,0x3fa5,
};
/*
7.85398125648498535156E-1,
3.77489470793079817668E-8,
2.69515142907905952645E-15,
*/
static unsigned short P1[] = {0x0000,0x4000,0x21fb,0x3fe9};
static unsigned short P2[] = {0x0000,0x0000,0x442d,0x3e64};
static unsigned short P3[] = {0x5170,0x98cc,0x4698,0x3ce8};
#define DP1 *(double *)P1
#define DP2 *(double *)P2
#define DP3 *(double *)P3
#endif
#ifdef MIEEE
static unsigned short sincof[] = {
0x3de5,0xd8fd,0x1fd1,0x9ccd,
0xbe5a,0xe5e5,0xa929,0x1f5d,
0x3ec7,0x1de3,0x567d,0x48a1,
0xbf2a,0x01a0,0x19bf,0xdf03,
0x3f81,0x1111,0x1110,0xf7d0,
0xbfc5,0x5555,0x5555,0x5548,
};
static unsigned short coscof[24] = {
0xbda8,0xfa49,0xa086,0x1a9b,
0x3e21,0xee9d,0x7b4e,0x3f05,
0xbe92,0x7e4f,0x7eac,0x4bc6,
0x3efa,0x01a0,0x19c8,0x44f5,
0xbf56,0xc16c,0x16c1,0x4f91,
0x3fa5,0x5555,0x5555,0x554b,
};
static unsigned short P1[] = {0x3fe9,0x21fb,0x4000,0x0000};
static unsigned short P2[] = {0x3e64,0x442d,0x0000,0x0000};
static unsigned short P3[] = {0x3ce8,0x4698,0x98cc,0x5170};
#define DP1 *(double *)P1
#define DP2 *(double *)P2
#define DP3 *(double *)P3
#endif
#ifdef ANSIPROT
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
extern double floor ( double );
extern double ldexp ( double, int );
extern int isnan ( double );
extern int isfinite ( double );
#else
double polevl(), floor(), ldexp();
int isnan(), isfinite();
#endif
extern double PIO4;
const static double lossth = 1.073741824e9;
#ifdef NANS
extern double NAN;
#endif
#ifdef INFINITIES
extern double INFINITY;
#endif
double sin(x)
double x;
{
double y, z, zz;
int j, sign;
#ifdef MINUSZERO
if( x == 0.0 )
return(x);
#endif
#ifdef NANS
if( isnan(x) )
return(x);
if( !isfinite(x) )
{
mtherr( "sin", DOMAIN );
return(NAN);
}
#endif
/* make argument positive but save the sign */
sign = 1;
if( x < 0 )
{
x = -x;
sign = -1;
}
if( x > lossth )
{
mtherr( "sin", TLOSS );
return(0.0);
}
y = floor( x/PIO4 ); /* integer part of x/PIO4 */
/* strip high bits of integer part to prevent integer overflow */
z = ldexp( y, -4 );
z = floor(z); /* integer part of y/8 */
z = y - ldexp( z, 4 ); /* y - 16 * (y/16) */
j = z; /* convert to integer for tests on the phase angle */
/* map zeros to origin */
if( j & 1 )
{
j += 1;
y += 1.0;
}
j = j & 07; /* octant modulo 360 degrees */
/* reflect in x axis */
if( j > 3)
{
sign = -sign;
j -= 4;
}
/* Extended precision modular arithmetic */
z = ((x - y * DP1) - y * DP2) - y * DP3;
zz = z * z;
if( (j==1) || (j==2) )
{
y = 1.0 - ldexp(zz,-1) + zz * zz * polevl( zz, coscof, 5 );
}
else
{
/* y = z + z * (zz * polevl( zz, sincof, 5 ));*/
y = z + z * z * z * polevl( zz, sincof, 5 );
}
if(sign < 0)
y = -y;
return(y);
}
double cos(x)
double x;
{
double y, z, zz;
long i;
int j, sign;
#ifdef NANS
if( isnan(x) )
return(x);
if( !isfinite(x) )
{
mtherr( "cos", DOMAIN );
return(NAN);
}
#endif
/* make argument positive */
sign = 1;
if( x < 0 )
x = -x;
if( x > lossth )
{
mtherr( "cos", TLOSS );
return(0.0);
}
y = floor( x/PIO4 );
z = ldexp( y, -4 );
z = floor(z); /* integer part of y/8 */
z = y - ldexp( z, 4 ); /* y - 16 * (y/16) */
/* integer and fractional part modulo one octant */
i = z;
if( i & 1 ) /* map zeros to origin */
{
i += 1;
y += 1.0;
}
j = i & 07;
if( j > 3)
{
j -=4;
sign = -sign;
}
if( j > 1 )
sign = -sign;
/* Extended precision modular arithmetic */
z = ((x - y * DP1) - y * DP2) - y * DP3;
zz = z * z;
if( (j==1) || (j==2) )
{
/* y = z + z * (zz * polevl( zz, sincof, 5 ));*/
y = z + z * z * z * polevl( zz, sincof, 5 );
}
else
{
y = 1.0 - ldexp(zz,-1) + zz * zz * polevl( zz, coscof, 5 );
}
if(sign < 0)
y = -y;
return(y);
}
/* Degrees, minutes, seconds to radians: */
/* 1 arc second, in radians = 4.8481368110953599358991410e-5 */
#ifdef DEC
static unsigned short P648[] = {034513,054170,0176773,0116043,};
#define P64800 *(double *)P648
#else
const static double P64800 = 4.8481368110953599358991410e-5;
#endif
double radian(d,m,s)
double d,m,s;
{
return( ((d*60.0 + m)*60.0 + s)*P64800 );
}

View File

@@ -0,0 +1,358 @@
/* sincos.c
*
* Circular sine and cosine of argument in degrees
* Table lookup and interpolation algorithm
*
*
*
* SYNOPSIS:
*
* double x, sine, cosine, flg, sincos();
*
* sincos( x, &sine, &cosine, flg );
*
*
*
* DESCRIPTION:
*
* Returns both the sine and the cosine of the argument x.
* Several different compile time options and minimax
* approximations are supplied to permit tailoring the
* tradeoff between computation speed and accuracy.
*
* Since range reduction is time consuming, the reduction
* of x modulo 360 degrees is also made optional.
*
* sin(i) is internally tabulated for 0 <= i <= 90 degrees.
* Approximation polynomials, ranging from linear interpolation
* to cubics in (x-i)**2, compute the sine and cosine
* of the residual x-i which is between -0.5 and +0.5 degree.
* In the case of the high accuracy options, the residual
* and the tabulated values are combined using the trigonometry
* formulas for sin(A+B) and cos(A+B).
*
* Compile time options are supplied for 5, 11, or 17 decimal
* relative accuracy (ACC5, ACC11, ACC17 respectively).
* A subroutine flag argument "flg" chooses betwen this
* accuracy and table lookup only (peak absolute error
* = 0.0087).
*
* If the argument flg = 1, then the tabulated value is
* returned for the nearest whole number of degrees. The
* approximation polynomials are not computed. At
* x = 0.5 deg, the absolute error is then sin(0.5) = 0.0087.
*
* An intermediate speed and precision can be obtained using
* the compile time option LINTERP and flg = 1. This yields
* a linear interpolation using a slope estimated from the sine
* or cosine at the nearest integer argument. The peak absolute
* error with this option is 3.8e-5. Relative error at small
* angles is about 1e-5.
*
* If flg = 0, then the approximation polynomials are computed
* and applied.
*
*
*
* SPEED:
*
* Relative speed comparisons follow for 6MHz IBM AT clone
* and Microsoft C version 4.0. These figures include
* software overhead of do loop and function calls.
* Since system hardware and software vary widely, the
* numbers should be taken as representative only.
*
* flg=0 flg=0 flg=1 flg=1
* ACC11 ACC5 LINTERP Lookup only
* In-line 8087 (/FPi)
* sin(), cos() 1.0 1.0 1.0 1.0
*
* In-line 8087 (/FPi)
* sincos() 1.1 1.4 1.9 3.0
*
* Software (/FPa)
* sin(), cos() 0.19 0.19 0.19 0.19
*
* Software (/FPa)
* sincos() 0.39 0.50 0.73 1.7
*
*
*
* ACCURACY:
*
* The accurate approximations are designed with a relative error
* criterion. The absolute error is greatest at x = 0.5 degree.
* It decreases from a local maximum at i+0.5 degrees to full
* machine precision at each integer i degrees. With the
* ACC5 option, the relative error of 6.3e-6 is equivalent to
* an absolute angular error of 0.01 arc second in the argument
* at x = i+0.5 degrees. For small angles < 0.5 deg, the ACC5
* accuracy is 6.3e-6 (.00063%) of reading; i.e., the absolute
* error decreases in proportion to the argument. This is true
* for both the sine and cosine approximations, since the latter
* is for the function 1 - cos(x).
*
* If absolute error is of most concern, use the compile time
* option ABSERR to obtain an absolute error of 2.7e-8 for ACC5
* precision. This is about half the absolute error of the
* relative precision option. In this case the relative error
* for small angles will increase to 9.5e-6 -- a reasonable
* tradeoff.
*/
#include "mconf.h"
/* Define one of the following to be 1:
*/
#define ACC5 1
#define ACC11 0
#define ACC17 0
/* Option for linear interpolation when flg = 1
*/
#define LINTERP 1
/* Option for absolute error criterion
*/
#define ABSERR 1
/* Option to include modulo 360 function:
*/
#define MOD360 1
/*
Cephes Math Library Release 2.1
Copyright 1987 by Stephen L. Moshier
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
*/
/* Table of sin(i degrees)
* for 0 <= i <= 90
*/
const static double sintbl[92] = {
0.00000000000000000000E0,
1.74524064372835128194E-2,
3.48994967025009716460E-2,
5.23359562429438327221E-2,
6.97564737441253007760E-2,
8.71557427476581735581E-2,
1.04528463267653471400E-1,
1.21869343405147481113E-1,
1.39173100960065444112E-1,
1.56434465040230869010E-1,
1.73648177666930348852E-1,
1.90808995376544812405E-1,
2.07911690817759337102E-1,
2.24951054343864998051E-1,
2.41921895599667722560E-1,
2.58819045102520762349E-1,
2.75637355816999185650E-1,
2.92371704722736728097E-1,
3.09016994374947424102E-1,
3.25568154457156668714E-1,
3.42020143325668733044E-1,
3.58367949545300273484E-1,
3.74606593415912035415E-1,
3.90731128489273755062E-1,
4.06736643075800207754E-1,
4.22618261740699436187E-1,
4.38371146789077417453E-1,
4.53990499739546791560E-1,
4.69471562785890775959E-1,
4.84809620246337029075E-1,
5.00000000000000000000E-1,
5.15038074910054210082E-1,
5.29919264233204954047E-1,
5.44639035015027082224E-1,
5.59192903470746830160E-1,
5.73576436351046096108E-1,
5.87785252292473129169E-1,
6.01815023152048279918E-1,
6.15661475325658279669E-1,
6.29320391049837452706E-1,
6.42787609686539326323E-1,
6.56059028990507284782E-1,
6.69130606358858213826E-1,
6.81998360062498500442E-1,
6.94658370458997286656E-1,
7.07106781186547524401E-1,
7.19339800338651139356E-1,
7.31353701619170483288E-1,
7.43144825477394235015E-1,
7.54709580222771997943E-1,
7.66044443118978035202E-1,
7.77145961456970879980E-1,
7.88010753606721956694E-1,
7.98635510047292846284E-1,
8.09016994374947424102E-1,
8.19152044288991789684E-1,
8.29037572555041692006E-1,
8.38670567945424029638E-1,
8.48048096156425970386E-1,
8.57167300702112287465E-1,
8.66025403784438646764E-1,
8.74619707139395800285E-1,
8.82947592858926942032E-1,
8.91006524188367862360E-1,
8.98794046299166992782E-1,
9.06307787036649963243E-1,
9.13545457642600895502E-1,
9.20504853452440327397E-1,
9.27183854566787400806E-1,
9.33580426497201748990E-1,
9.39692620785908384054E-1,
9.45518575599316810348E-1,
9.51056516295153572116E-1,
9.56304755963035481339E-1,
9.61261695938318861916E-1,
9.65925826289068286750E-1,
9.70295726275996472306E-1,
9.74370064785235228540E-1,
9.78147600733805637929E-1,
9.81627183447663953497E-1,
9.84807753012208059367E-1,
9.87688340595137726190E-1,
9.90268068741570315084E-1,
9.92546151641322034980E-1,
9.94521895368273336923E-1,
9.96194698091745532295E-1,
9.97564050259824247613E-1,
9.98629534754573873784E-1,
9.99390827019095730006E-1,
9.99847695156391239157E-1,
1.00000000000000000000E0,
9.99847695156391239157E-1,
};
#ifdef ANSIPROT
double floor ( double );
#else
double floor();
#endif
int sincos(x, s, c, flg)
double x;
double *s, *c;
int flg;
{
int ix, ssign, csign, xsign;
double y, z, sx, sz, cx, cz;
/* Make argument nonnegative.
*/
xsign = 1;
if( x < 0.0 )
{
xsign = -1;
x = -x;
}
#if MOD360
x = x - 360.0 * floor( x/360.0 );
#endif
/* Find nearest integer to x.
* Note there should be a domain error test here,
* but this is omitted to gain speed.
*/
ix = x + 0.5;
z = x - ix; /* the residual */
/* Look up the sine and cosine of the integer.
*/
if( ix <= 180 )
{
ssign = 1;
csign = 1;
}
else
{
ssign = -1;
csign = -1;
ix -= 180;
}
if( ix > 90 )
{
csign = -csign;
ix = 180 - ix;
}
sx = sintbl[ix];
if( ssign < 0 )
sx = -sx;
cx = sintbl[ 90-ix ];
if( csign < 0 )
cx = -cx;
/* If the flag argument is set, then just return
* the tabulated values for arg to the nearest whole degree.
*/
if( flg )
{
#if LINTERP
y = sx + 1.74531263774940077459e-2 * z * cx;
cx -= 1.74531263774940077459e-2 * z * sx;
sx = y;
#endif
if( xsign < 0 )
sx = -sx;
*s = sx; /* sine */
*c = cx; /* cosine */
return 0;
}
/* Find sine and cosine
* of the residual angle between -0.5 and +0.5 degree.
*/
#if ACC5
#if ABSERR
/* absolute error = 2.769e-8: */
sz = 1.74531263774940077459e-2 * z;
/* absolute error = 4.146e-11: */
cz = 1.0 - 1.52307909153324666207e-4 * z * z;
#else
/* relative error = 6.346e-6: */
sz = 1.74531817576426662296e-2 * z;
/* relative error = 3.173e-6: */
cz = 1.0 - 1.52308226602566149927e-4 * z * z;
#endif
#else
y = z * z;
#endif
#if ACC11
sz = ( -8.86092781698004819918e-7 * y
+ 1.74532925198378577601e-2 ) * z;
cz = 1.0 - ( -3.86631403698859047896e-9 * y
+ 1.52308709893047593702e-4 ) * y;
#endif
#if ACC17
sz = (( 1.34959795251974073996e-11 * y
- 8.86096155697856783296e-7 ) * y
+ 1.74532925199432957214e-2 ) * z;
cz = 1.0 - (( 3.92582397764340914444e-14 * y
- 3.86632385155548605680e-9 ) * y
+ 1.52308709893354299569e-4 ) * y;
#endif
/* Combine the tabulated part and the calculated part
* by trigonometry.
*/
y = sx * cz + cx * sz;
if( xsign < 0 )
y = - y;
*s = y; /* sine */
*c = cx * cz - sx * sz; /* cosine */
return 0;
}

View File

@@ -0,0 +1,308 @@
/* sindg.c
*
* Circular sine of angle in degrees
*
*
*
* SYNOPSIS:
*
* double x, y, sindg();
*
* y = sindg( x );
*
*
*
* DESCRIPTION:
*
* Range reduction is into intervals of 45 degrees.
*
* Two polynomial approximating functions are employed.
* Between 0 and pi/4 the sine is approximated by
* x + x**3 P(x**2).
* Between pi/4 and pi/2 the cosine is represented as
* 1 - x**2 P(x**2).
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC +-1000 3100 3.3e-17 9.0e-18
* IEEE +-1000 30000 2.3e-16 5.6e-17
*
* ERROR MESSAGES:
*
* message condition value returned
* sindg total loss x > 8.0e14 (DEC) 0.0
* x > 1.0e14 (IEEE)
*
*/
/* cosdg.c
*
* Circular cosine of angle in degrees
*
*
*
* SYNOPSIS:
*
* double x, y, cosdg();
*
* y = cosdg( x );
*
*
*
* DESCRIPTION:
*
* Range reduction is into intervals of 45 degrees.
*
* Two polynomial approximating functions are employed.
* Between 0 and pi/4 the cosine is approximated by
* 1 - x**2 P(x**2).
* Between pi/4 and pi/2 the sine is represented as
* x + x**3 P(x**2).
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC +-1000 3400 3.5e-17 9.1e-18
* IEEE +-1000 30000 2.1e-16 5.7e-17
* See also sin().
*
*/
/* Cephes Math Library Release 2.0: April, 1987
* Copyright 1985, 1987 by Stephen L. Moshier
* Direct inquiries to 30 Frost Street, Cambridge, MA 02140 */
#include "mconf.h"
#ifdef UNK
const static double sincof[] = {
1.58962301572218447952E-10,
-2.50507477628503540135E-8,
2.75573136213856773549E-6,
-1.98412698295895384658E-4,
8.33333333332211858862E-3,
-1.66666666666666307295E-1
};
const static double coscof[] = {
1.13678171382044553091E-11,
-2.08758833757683644217E-9,
2.75573155429816611547E-7,
-2.48015872936186303776E-5,
1.38888888888806666760E-3,
-4.16666666666666348141E-2,
4.99999999999999999798E-1
};
const static double PI180 = 1.74532925199432957692E-2; /* pi/180 */
const static double lossth = 1.0e14;
#endif
#ifdef DEC
static unsigned short sincof[] = {
0030056,0143750,0177170,0073013,
0131727,0027455,0044510,0132205,
0033470,0167432,0131752,0042263,
0135120,0006400,0146776,0174027,
0036410,0104210,0104207,0137202,
0137452,0125252,0125252,0125103
};
static unsigned short coscof[] = {
0027107,0176030,0153315,0110312,
0131017,0072476,0007450,0123243,
0032623,0171174,0070066,0146445,
0134320,0006400,0147355,0163313,
0035666,0005540,0133012,0165067,
0137052,0125252,0125252,0125206,
0040000,0000000,0000000,0000000
};
static unsigned short P1[] = {0036616,0175065,0011224,0164711};
#define PI180 *(double *)P1
const static double lossth = 8.0e14;
#endif
#ifdef IBMPC
static unsigned short sincof[] = {
0x0ec1,0x1fcf,0xd8fd,0x3de5,
0x1691,0xa929,0xe5e5,0xbe5a,
0x4896,0x567d,0x1de3,0x3ec7,
0xdf03,0x19bf,0x01a0,0xbf2a,
0xf7d0,0x1110,0x1111,0x3f81,
0x5548,0x5555,0x5555,0xbfc5
};
static unsigned short coscof[] = {
0xb219,0x1ad9,0xff83,0x3da8,
0x14d4,0xc1e5,0xeea7,0xbe21,
0xd9a5,0x8e06,0x7e4f,0x3e92,
0xbcd9,0x19dd,0x01a0,0xbefa,
0x5d47,0x16c1,0xc16c,0x3f56,
0x5551,0x5555,0x5555,0xbfa5,
0x0000,0x0000,0x0000,0x3fe0
};
static unsigned short P1[] = {0x9d39,0xa252,0xdf46,0x3f91};
#define PI180 *(double *)P1
const static double lossth = 1.0e14;
#endif
#ifdef MIEEE
static unsigned short sincof[] = {
0x3de5,0xd8fd,0x1fcf,0x0ec1,
0xbe5a,0xe5e5,0xa929,0x1691,
0x3ec7,0x1de3,0x567d,0x4896,
0xbf2a,0x01a0,0x19bf,0xdf03,
0x3f81,0x1111,0x1110,0xf7d0,
0xbfc5,0x5555,0x5555,0x5548
};
static unsigned short coscof[] = {
0x3da8,0xff83,0x1ad9,0xb219,
0xbe21,0xeea7,0xc1e5,0x14d4,
0x3e92,0x7e4f,0x8e06,0xd9a5,
0xbefa,0x01a0,0x19dd,0xbcd9,
0x3f56,0xc16c,0x16c1,0x5d47,
0xbfa5,0x5555,0x5555,0x5551,
0x3fe0,0x0000,0x0000,0x0000
};
static unsigned short P1[] = {
0x3f91,0xdf46,0xa252,0x9d39
};
#define PI180 *(double *)P1
const static double lossth = 1.0e14;
#endif
#ifdef ANSIPROT
extern double polevl ( double, void *, int );
extern double floor ( double );
extern double ldexp ( double, int );
#else
double polevl(), floor(), ldexp();
#endif
extern double PIO4;
double sindg(x)
double x;
{
double y, z, zz;
int j, sign;
/* make argument positive but save the sign */
sign = 1;
if( x < 0 )
{
x = -x;
sign = -1;
}
if( x > lossth )
{
mtherr( "sindg", TLOSS );
return(0.0);
}
y = floor( x/45.0 ); /* integer part of x/PIO4 */
/* strip high bits of integer part to prevent integer overflow */
z = ldexp( y, -4 );
z = floor(z); /* integer part of y/8 */
z = y - ldexp( z, 4 ); /* y - 16 * (y/16) */
j = z; /* convert to integer for tests on the phase angle */
/* map zeros to origin */
if( j & 1 )
{
j += 1;
y += 1.0;
}
j = j & 07; /* octant modulo 360 degrees */
/* reflect in x axis */
if( j > 3)
{
sign = -sign;
j -= 4;
}
z = x - y * 45.0; /* x mod 45 degrees */
z *= PI180; /* multiply by pi/180 to convert to radians */
zz = z * z;
if( (j==1) || (j==2) )
{
y = 1.0 - zz * polevl( zz, coscof, 6 );
}
else
{
y = z + z * (zz * polevl( zz, sincof, 5 ));
}
if(sign < 0)
y = -y;
return(y);
}
double cosdg(x)
double x;
{
double y, z, zz;
int j, sign;
/* make argument positive */
sign = 1;
if( x < 0 )
x = -x;
if( x > lossth )
{
mtherr( "cosdg", TLOSS );
return(0.0);
}
y = floor( x/45.0 );
z = ldexp( y, -4 );
z = floor(z); /* integer part of y/8 */
z = y - ldexp( z, 4 ); /* y - 16 * (y/16) */
/* integer and fractional part modulo one octant */
j = z;
if( j & 1 ) /* map zeros to origin */
{
j += 1;
y += 1.0;
}
j = j & 07;
if( j > 3)
{
j -=4;
sign = -sign;
}
if( j > 1 )
sign = -sign;
z = x - y * 45.0; /* x mod 45 degrees */
z *= PI180; /* multiply by pi/180 to convert to radians */
zz = z * z;
if( (j==1) || (j==2) )
{
y = z + z * (zz * polevl( zz, sincof, 5 ));
}
else
{
y = 1.0 - zz * polevl( zz, coscof, 6 );
}
if(sign < 0)
y = -y;
return(y);
}

View File

@@ -0,0 +1,148 @@
/* sinh.c
*
* Hyperbolic sine
*
*
*
* SYNOPSIS:
*
* double x, y, sinh();
*
* y = sinh( x );
*
*
*
* DESCRIPTION:
*
* Returns hyperbolic sine of argument in the range MINLOG to
* MAXLOG.
*
* The range is partitioned into two segments. If |x| <= 1, a
* rational function of the form x + x**3 P(x)/Q(x) is employed.
* Otherwise the calculation is sinh(x) = ( exp(x) - exp(-x) )/2.
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC +- 88 50000 4.0e-17 7.7e-18
* IEEE +-MAXLOG 30000 2.6e-16 5.7e-17
*
*/
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
#ifdef UNK
const static double P[] = {
-7.89474443963537015605E-1,
-1.63725857525983828727E2,
-1.15614435765005216044E4,
-3.51754964808151394800E5
};
const static double Q[] = {
/* 1.00000000000000000000E0,*/
-2.77711081420602794433E2,
3.61578279834431989373E4,
-2.11052978884890840399E6
};
#endif
#ifdef DEC
static unsigned short P[] = {
0140112,0015377,0042731,0163255,
0142043,0134721,0146177,0123761,
0143464,0122706,0034353,0006017,
0144653,0140536,0157665,0054045
};
static unsigned short Q[] = {
/*0040200,0000000,0000000,0000000,*/
0142212,0155404,0133513,0022040,
0044015,0036723,0173271,0011053,
0145400,0150407,0023710,0001034
};
#endif
#ifdef IBMPC
static unsigned short P[] = {
0x3cd6,0xe8bb,0x435f,0xbfe9,
0xf4fe,0x398f,0x773a,0xc064,
0x6182,0xc71d,0x94b8,0xc0c6,
0xab05,0xdbf6,0x782b,0xc115
};
static unsigned short Q[] = {
/*0x0000,0x0000,0x0000,0x3ff0,*/
0x6484,0x96e9,0x5b60,0xc071,
0x2245,0x7ed7,0xa7ba,0x40e1,
0x0044,0xe4f9,0x1a20,0xc140
};
#endif
#ifdef MIEEE
static unsigned short P[] = {
0xbfe9,0x435f,0xe8bb,0x3cd6,
0xc064,0x773a,0x398f,0xf4fe,
0xc0c6,0x94b8,0xc71d,0x6182,
0xc115,0x782b,0xdbf6,0xab05
};
static unsigned short Q[] = {
0xc071,0x5b60,0x96e9,0x6484,
0x40e1,0xa7ba,0x7ed7,0x2245,
0xc140,0x1a20,0xe4f9,0x0044
};
#endif
#ifdef ANSIPROT
extern double fabs ( double );
extern double exp ( double );
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
#else
double fabs(), exp(), polevl(), p1evl();
#endif
extern double INFINITY, MINLOG, MAXLOG, LOGE2;
double sinh(x)
double x;
{
double a;
#ifdef MINUSZERO
if( x == 0.0 )
return(x);
#endif
a = fabs(x);
if( (x > (MAXLOG + LOGE2)) || (x > -(MINLOG-LOGE2) ) )
{
mtherr( "sinh", DOMAIN );
if( x > 0 )
return( INFINITY );
else
return( -INFINITY );
}
if( a > 1.0 )
{
if( a >= (MAXLOG - LOGE2) )
{
a = exp(0.5*a);
a = (0.5 * a) * a;
if( x < 0 )
a = -a;
return(a);
}
a = exp(a);
a = 0.5*a - (0.5/a);
if( x < 0 )
a = -a;
return(a);
}
a *= a;
return( x + x * a * (polevl(a,P,3)/p1evl(a,Q,3)) );
}

View File

@@ -0,0 +1,178 @@
/* sqrt.c
*
* Square root
*
*
*
* SYNOPSIS:
*
* double x, y, sqrt();
*
* y = sqrt( x );
*
*
*
* DESCRIPTION:
*
* Returns the square root of x.
*
* Range reduction involves isolating the power of two of the
* argument and using a polynomial approximation to obtain
* a rough value for the square root. Then Heron's iteration
* is used three times to converge to an accurate value.
*
*
*
* ACCURACY:
*
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC 0, 10 60000 2.1e-17 7.9e-18
* IEEE 0,1.7e308 30000 1.7e-16 6.3e-17
*
*
* ERROR MESSAGES:
*
* message condition value returned
* sqrt domain x < 0 0.0
*
*/
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1987, 1988, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
#ifdef ANSIPROT
extern double frexp ( double, int * );
extern double ldexp ( double, int );
#else
double frexp(), ldexp();
#endif
extern double SQRT2; /* SQRT2 = 1.41421356237309504880 */
double sqrt(x)
double x;
{
int e;
#ifndef UNK
short *q;
#endif
double z, w;
if( x <= 0.0 )
{
if( x < 0.0 )
mtherr( "sqrt", DOMAIN );
return( 0.0 );
}
w = x;
/* separate exponent and significand */
#ifdef UNK
z = frexp( x, &e );
#endif
#ifdef DEC
q = (short *)&x;
e = ((*q >> 7) & 0377) - 0200;
*q &= 0177;
*q |= 040000;
z = x;
#endif
/* Note, frexp and ldexp are used in order to
* handle denormal numbers properly.
*/
#ifdef IBMPC
z = frexp( x, &e );
q = (short *)&x;
q += 3;
/*
e = ((*q >> 4) & 0x0fff) - 0x3fe;
*q &= 0x000f;
*q |= 0x3fe0;
z = x;
*/
#endif
#ifdef MIEEE
z = frexp( x, &e );
q = (short *)&x;
/*
e = ((*q >> 4) & 0x0fff) - 0x3fe;
*q &= 0x000f;
*q |= 0x3fe0;
z = x;
*/
#endif
/* approximate square root of number between 0.5 and 1
* relative error of approximation = 7.47e-3
*/
x = 4.173075996388649989089E-1 + 5.9016206709064458299663E-1 * z;
/* adjust for odd powers of 2 */
if( (e & 1) != 0 )
x *= SQRT2;
/* re-insert exponent */
#ifdef UNK
x = ldexp( x, (e >> 1) );
#endif
#ifdef DEC
*q += ((e >> 1) & 0377) << 7;
*q &= 077777;
#endif
#ifdef IBMPC
x = ldexp( x, (e >> 1) );
/*
*q += ((e >>1) & 0x7ff) << 4;
*q &= 077777;
*/
#endif
#ifdef MIEEE
x = ldexp( x, (e >> 1) );
/*
*q += ((e >>1) & 0x7ff) << 4;
*q &= 077777;
*/
#endif
/* Newton iterations: */
#ifdef UNK
x = 0.5*(x + w/x);
x = 0.5*(x + w/x);
x = 0.5*(x + w/x);
#endif
/* Note, assume the square root cannot be denormal,
* so it is safe to use integer exponent operations here.
*/
#ifdef DEC
x += w/x;
*q -= 0200;
x += w/x;
*q -= 0200;
x += w/x;
*q -= 0200;
#endif
#ifdef IBMPC
x += w/x;
*q -= 0x10;
x += w/x;
*q -= 0x10;
x += w/x;
*q -= 0x10;
#endif
#ifdef MIEEE
x += w/x;
*q -= 0x10;
x += w/x;
*q -= 0x10;
x += w/x;
*q -= 0x10;
#endif
return(x);
}

View File

@@ -0,0 +1,304 @@
/* tan.c
*
* Circular tangent
*
*
*
* SYNOPSIS:
*
* double x, y, tan();
*
* y = tan( x );
*
*
*
* DESCRIPTION:
*
* Returns the circular tangent of the radian argument x.
*
* Range reduction is modulo pi/4. A rational function
* x + x**3 P(x**2)/Q(x**2)
* is employed in the basic interval [0, pi/4].
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC +-1.07e9 44000 4.1e-17 1.0e-17
* IEEE +-1.07e9 30000 2.9e-16 8.1e-17
*
* ERROR MESSAGES:
*
* message condition value returned
* tan total loss x > 1.073741824e9 0.0
*
*/
/* cot.c
*
* Circular cotangent
*
*
*
* SYNOPSIS:
*
* double x, y, cot();
*
* y = cot( x );
*
*
*
* DESCRIPTION:
*
* Returns the circular cotangent of the radian argument x.
*
* Range reduction is modulo pi/4. A rational function
* x + x**3 P(x**2)/Q(x**2)
* is employed in the basic interval [0, pi/4].
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* IEEE +-1.07e9 30000 2.9e-16 8.2e-17
*
*
* ERROR MESSAGES:
*
* message condition value returned
* cot total loss x > 1.073741824e9 0.0
* cot singularity x = 0 INFINITY
*
*/
/*
Cephes Math Library Release 2.8: June, 2000
yright 1984, 1995, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
#ifdef UNK
const static double P[] = {
-1.30936939181383777646E4,
1.15351664838587416140E6,
-1.79565251976484877988E7
};
const static double Q[] = {
/* 1.00000000000000000000E0,*/
1.36812963470692954678E4,
-1.32089234440210967447E6,
2.50083801823357915839E7,
-5.38695755929454629881E7
};
const static double DP1 = 7.853981554508209228515625E-1;
const static double DP2 = 7.94662735614792836714E-9;
const static double DP3 = 3.06161699786838294307E-17;
const static double lossth = 1.073741824e9;
#endif
#ifdef DEC
static unsigned short P[] = {
0143514,0113306,0111171,0174674,
0045214,0147545,0027744,0167346,
0146210,0177526,0114514,0105660
};
static unsigned short Q[] = {
/*0040200,0000000,0000000,0000000,*/
0043525,0142457,0072633,0025617,
0145241,0036742,0140525,0162256,
0046276,0146176,0013526,0143573,
0146515,0077401,0162762,0150607
};
/* 7.853981629014015197753906250000E-1 */
static unsigned short P1[] = {0040111,0007732,0120000,0000000,};
/* 4.960467869796758577649598009884E-10 */
static unsigned short P2[] = {0030410,0055060,0100000,0000000,};
/* 2.860594363054915898381331279295E-18 */
static unsigned short P3[] = {0021523,0011431,0105056,0001560,};
#define DP1 *(double *)P1
#define DP2 *(double *)P2
#define DP3 *(double *)P3
const static double lossth = 1.073741824e9;
#endif
#ifdef IBMPC
static unsigned short P[] = {
0x3f38,0xd24f,0x92d8,0xc0c9,
0x9ddd,0xa5fc,0x99ec,0x4131,
0x9176,0xd329,0x1fea,0xc171
};
static unsigned short Q[] = {
/*0x0000,0x0000,0x0000,0x3ff0,*/
0x6572,0xeeb3,0xb8a5,0x40ca,
0xbc96,0x582a,0x27bc,0xc134,
0xd8ef,0xc2ea,0xd98f,0x4177,
0x5a31,0x3cbe,0xafe0,0xc189
};
/*
7.85398125648498535156E-1,
3.77489470793079817668E-8,
2.69515142907905952645E-15,
*/
static unsigned short P1[] = {0x0000,0x4000,0x21fb,0x3fe9};
static unsigned short P2[] = {0x0000,0x0000,0x442d,0x3e64};
static unsigned short P3[] = {0x5170,0x98cc,0x4698,0x3ce8};
#define DP1 *(double *)P1
#define DP2 *(double *)P2
#define DP3 *(double *)P3
const static double lossth = 1.073741824e9;
#endif
#ifdef MIEEE
static unsigned short P[] = {
0xc0c9,0x92d8,0xd24f,0x3f38,
0x4131,0x99ec,0xa5fc,0x9ddd,
0xc171,0x1fea,0xd329,0x9176
};
static unsigned short Q[] = {
0x40ca,0xb8a5,0xeeb3,0x6572,
0xc134,0x27bc,0x582a,0xbc96,
0x4177,0xd98f,0xc2ea,0xd8ef,
0xc189,0xafe0,0x3cbe,0x5a31
};
static unsigned short P1[] = {
0x3fe9,0x21fb,0x4000,0x0000
};
static unsigned short P2[] = {
0x3e64,0x442d,0x0000,0x0000
};
static unsigned short P3[] = {
0x3ce8,0x4698,0x98cc,0x5170,
};
#define DP1 *(double *)P1
#define DP2 *(double *)P2
#define DP3 *(double *)P3
const static double lossth = 1.073741824e9;
#endif
#ifdef ANSIPROT
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
extern double floor ( double );
extern double ldexp ( double, int );
extern int isnan ( double );
extern int isfinite ( double );
const static double tancot(double, int);
#else
double polevl(), p1evl(), floor(), ldexp();
const static double tancot();
int isnan(), isfinite();
#endif
extern double PIO4;
extern double INFINITY;
extern double NAN;
double tan(x)
double x;
{
#ifdef MINUSZERO
if( x == 0.0 )
return(x);
#endif
#ifdef NANS
if( isnan(x) )
return(x);
if( !isfinite(x) )
{
mtherr( "tan", DOMAIN );
return(NAN);
}
#endif
return( tancot(x,0) );
}
double cot(x)
double x;
{
if( x == 0.0 )
{
mtherr( "cot", SING );
return( INFINITY );
}
return( tancot(x,1) );
}
const static double tancot( xx, cotflg )
double xx;
int cotflg;
{
double x, y, z, zz;
int j, sign;
/* make argument positive but save the sign */
if( xx < 0 )
{
x = -xx;
sign = -1;
}
else
{
x = xx;
sign = 1;
}
if( x > lossth )
{
if( cotflg )
mtherr( "cot", TLOSS );
else
mtherr( "tan", TLOSS );
return(0.0);
}
/* compute x mod PIO4 */
y = floor( x/PIO4 );
/* strip high bits of integer part */
z = ldexp( y, -3 );
z = floor(z); /* integer part of y/8 */
z = y - ldexp( z, 3 ); /* y - 16 * (y/16) */
/* integer and fractional part modulo one octant */
j = z;
/* map zeros and singularities to origin */
if( j & 1 )
{
j += 1;
y += 1.0;
}
z = ((x - y * DP1) - y * DP2) - y * DP3;
zz = z * z;
if( zz > 1.0e-14 )
y = z + z * (zz * polevl( zz, P, 2 )/p1evl(zz, Q, 4));
else
y = z;
if( j & 2 )
{
if( cotflg )
y = -y;
else
y = -1.0/y;
}
else
{
if( cotflg )
y = 1.0/y;
}
if( sign < 0 )
y = -y;
return( y );
}

View File

@@ -0,0 +1,267 @@
/* tandg.c
*
* Circular tangent of argument in degrees
*
*
*
* SYNOPSIS:
*
* double x, y, tandg();
*
* y = tandg( x );
*
*
*
* DESCRIPTION:
*
* Returns the circular tangent of the argument x in degrees.
*
* Range reduction is modulo pi/4. A rational function
* x + x**3 P(x**2)/Q(x**2)
* is employed in the basic interval [0, pi/4].
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC 0,10 8000 3.4e-17 1.2e-17
* IEEE 0,10 30000 3.2e-16 8.4e-17
*
* ERROR MESSAGES:
*
* message condition value returned
* tandg total loss x > 8.0e14 (DEC) 0.0
* x > 1.0e14 (IEEE)
* tandg singularity x = 180 k + 90 MAXNUM
*/
/* cotdg.c
*
* Circular cotangent of argument in degrees
*
*
*
* SYNOPSIS:
*
* double x, y, cotdg();
*
* y = cotdg( x );
*
*
*
* DESCRIPTION:
*
* Returns the circular cotangent of the argument x in degrees.
*
* Range reduction is modulo pi/4. A rational function
* x + x**3 P(x**2)/Q(x**2)
* is employed in the basic interval [0, pi/4].
*
*
* ERROR MESSAGES:
*
* message condition value returned
* cotdg total loss x > 8.0e14 (DEC) 0.0
* x > 1.0e14 (IEEE)
* cotdg singularity x = 180 k MAXNUM
*/
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1987, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
#ifdef UNK
const static double P[] = {
-1.30936939181383777646E4,
1.15351664838587416140E6,
-1.79565251976484877988E7
};
const static double Q[] = {
/* 1.00000000000000000000E0,*/
1.36812963470692954678E4,
-1.32089234440210967447E6,
2.50083801823357915839E7,
-5.38695755929454629881E7
};
const static double PI180 = 1.74532925199432957692E-2;
const static double lossth = 1.0e14;
#endif
#ifdef DEC
static unsigned short P[] = {
0143514,0113306,0111171,0174674,
0045214,0147545,0027744,0167346,
0146210,0177526,0114514,0105660
};
static unsigned short Q[] = {
/*0040200,0000000,0000000,0000000,*/
0043525,0142457,0072633,0025617,
0145241,0036742,0140525,0162256,
0046276,0146176,0013526,0143573,
0146515,0077401,0162762,0150607
};
static unsigned short P1[] = {0036616,0175065,0011224,0164711};
#define PI180 *(double *)P1
const static double lossth = 8.0e14;
#endif
#ifdef IBMPC
static unsigned short P[] = {
0x3f38,0xd24f,0x92d8,0xc0c9,
0x9ddd,0xa5fc,0x99ec,0x4131,
0x9176,0xd329,0x1fea,0xc171
};
static unsigned short Q[] = {
/*0x0000,0x0000,0x0000,0x3ff0,*/
0x6572,0xeeb3,0xb8a5,0x40ca,
0xbc96,0x582a,0x27bc,0xc134,
0xd8ef,0xc2ea,0xd98f,0x4177,
0x5a31,0x3cbe,0xafe0,0xc189
};
static unsigned short P1[] = {0x9d39,0xa252,0xdf46,0x3f91};
#define PI180 *(double *)P1
const static double lossth = 1.0e14;
#endif
#ifdef MIEEE
static unsigned short P[] = {
0xc0c9,0x92d8,0xd24f,0x3f38,
0x4131,0x99ec,0xa5fc,0x9ddd,
0xc171,0x1fea,0xd329,0x9176
};
static unsigned short Q[] = {
0x40ca,0xb8a5,0xeeb3,0x6572,
0xc134,0x27bc,0x582a,0xbc96,
0x4177,0xd98f,0xc2ea,0xd8ef,
0xc189,0xafe0,0x3cbe,0x5a31
};
static unsigned short P1[] = {
0x3f91,0xdf46,0xa252,0x9d39
};
#define PI180 *(double *)P1
const static double lossth = 1.0e14;
#endif
#ifdef ANSIPROT
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
extern double floor ( double );
extern double ldexp ( double, int );
const static double tancot( double, int );
#else
double polevl(), p1evl(), floor(), ldexp();
const static double tancot();
#endif
extern double MAXNUM;
extern double PIO4;
double tandg(x)
double x;
{
return( tancot(x,0) );
}
double cotdg(x)
double x;
{
return( tancot(x,1) );
}
const static double tancot( xx, cotflg )
double xx;
int cotflg;
{
double x, y, z, zz;
int j, sign;
/* make argument positive but save the sign */
if( xx < 0 )
{
x = -xx;
sign = -1;
}
else
{
x = xx;
sign = 1;
}
if( x > lossth )
{
mtherr( "tandg", TLOSS );
return(0.0);
}
/* compute x mod PIO4 */
y = floor( x/45.0 );
/* strip high bits of integer part */
z = ldexp( y, -3 );
z = floor(z); /* integer part of y/8 */
z = y - ldexp( z, 3 ); /* y - 16 * (y/16) */
/* integer and fractional part modulo one octant */
j = z;
/* map zeros and singularities to origin */
if( j & 1 )
{
j += 1;
y += 1.0;
}
z = x - y * 45.0;
z *= PI180;
zz = z * z;
if( zz > 1.0e-14 )
y = z + z * (zz * polevl( zz, P, 2 )/p1evl(zz, Q, 4));
else
y = z;
if( j & 2 )
{
if( cotflg )
y = -y;
else
{
if( y != 0.0 )
{
y = -1.0/y;
}
else
{
mtherr( "tandg", SING );
y = MAXNUM;
}
}
}
else
{
if( cotflg )
{
if( y != 0.0 )
y = 1.0/y;
else
{
mtherr( "cotdg", SING );
y = MAXNUM;
}
}
}
if( sign < 0 )
y = -y;
return( y );
}

View File

@@ -0,0 +1,141 @@
/* tanh.c
*
* Hyperbolic tangent
*
*
*
* SYNOPSIS:
*
* double x, y, tanh();
*
* y = tanh( x );
*
*
*
* DESCRIPTION:
*
* Returns hyperbolic tangent of argument in the range MINLOG to
* MAXLOG.
*
* A rational function is used for |x| < 0.625. The form
* x + x**3 P(x)/Q(x) of Cody _& Waite is employed.
* Otherwise,
* tanh(x) = sinh(x)/cosh(x) = 1 - 2/(exp(2x) + 1).
*
*
*
* ACCURACY:
*
* Relative error:
* arithmetic domain # trials peak rms
* DEC -2,2 50000 3.3e-17 6.4e-18
* IEEE -2,2 30000 2.5e-16 5.8e-17
*
*/
/*
Cephes Math Library Release 2.8: June, 2000
Copyright 1984, 1995, 2000 by Stephen L. Moshier
*/
#include "mconf.h"
#ifdef UNK
const static double P[] = {
-9.64399179425052238628E-1,
-9.92877231001918586564E1,
-1.61468768441708447952E3
};
const static double Q[] = {
/* 1.00000000000000000000E0,*/
1.12811678491632931402E2,
2.23548839060100448583E3,
4.84406305325125486048E3
};
#endif
#ifdef DEC
static unsigned short P[] = {
0140166,0161335,0053753,0075126,
0141706,0111520,0070463,0040552,
0142711,0153001,0101300,0025430
};
static unsigned short Q[] = {
/*0040200,0000000,0000000,0000000,*/
0041741,0117624,0051300,0156060,
0043013,0133720,0071251,0127717,
0043227,0060201,0021020,0020136
};
#endif
#ifdef IBMPC
static unsigned short P[] = {
0x6f4b,0xaafd,0xdc5b,0xbfee,
0x682d,0x0e26,0xd26a,0xc058,
0x0563,0x3058,0x3ac0,0xc099
};
static unsigned short Q[] = {
/*0x0000,0x0000,0x0000,0x3ff0,*/
0x1b86,0x8a58,0x33f2,0x405c,
0x35fa,0x0e55,0x76fa,0x40a1,
0x040c,0x2442,0xec10,0x40b2
};
#endif
#ifdef MIEEE
static unsigned short P[] = {
0xbfee,0xdc5b,0xaafd,0x6f4b,
0xc058,0xd26a,0x0e26,0x682d,
0xc099,0x3ac0,0x3058,0x0563
};
static unsigned short Q[] = {
0x405c,0x33f2,0x8a58,0x1b86,
0x40a1,0x76fa,0x0e55,0x35fa,
0x40b2,0xec10,0x2442,0x040c
};
#endif
#ifdef ANSIPROT
extern double fabs ( double );
extern double exp ( double );
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
#else
double fabs(), exp(), polevl(), p1evl();
#endif
extern double MAXLOG;
double tanh(x)
double x;
{
double s, z;
#ifdef MINUSZERO
if( x == 0.0 )
return(x);
#endif
z = fabs(x);
if( z > 0.5 * MAXLOG )
{
if( x > 0 )
return( 1.0 );
else
return( -1.0 );
}
if( z >= 0.625 )
{
s = exp(2.0*z);
z = 1.0 - 2.0/(s + 1.0);
if( x < 0 )
z = -z;
}
else
{
if( x == 0.0 )
return(x);
s = x * x;
z = polevl( s, P, 2 )/p1evl(s, Q, 3);
z = x * s * z;
z = x + z;
}
return( z );
}

View File

@@ -0,0 +1,138 @@
/* unity.c
*
* Relative error approximations for function arguments near
* unity.
*
* log1p(x) = log(1+x)
* expm1(x) = exp(x) - 1
* cosm1(x) = cos(x) - 1
*
*/
#include "mconf.h"
#ifdef ANSIPROT
extern int isnan (double);
extern int isfinite (double);
extern double log ( double );
extern double polevl ( double, void *, int );
extern double p1evl ( double, void *, int );
extern double exp ( double );
extern double cos ( double );
#else
double log(), polevl(), p1evl(), exp(), cos();
int isnan(), isfinite();
#endif
extern double INFINITY;
/* log1p(x) = log(1 + x) */
/* Coefficients for log(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
* 1/sqrt(2) <= x < sqrt(2)
* Theoretical peak relative error = 2.32e-20
*/
const static double LP[] = {
4.5270000862445199635215E-5,
4.9854102823193375972212E-1,
6.5787325942061044846969E0,
2.9911919328553073277375E1,
6.0949667980987787057556E1,
5.7112963590585538103336E1,
2.0039553499201281259648E1,
};
const static double LQ[] = {
/* 1.0000000000000000000000E0,*/
1.5062909083469192043167E1,
8.3047565967967209469434E1,
2.2176239823732856465394E2,
3.0909872225312059774938E2,
2.1642788614495947685003E2,
6.0118660497603843919306E1,
};
#define SQRTH 0.70710678118654752440
#define SQRT2 1.41421356237309504880
double log1p(x)
double x;
{
double z;
z = 1.0 + x;
if( (z < SQRTH) || (z > SQRT2) )
return( log(z) );
z = x*x;
z = -0.5 * z + x * ( z * polevl( x, LP, 6 ) / p1evl( x, LQ, 6 ) );
return (x + z);
}
/* expm1(x) = exp(x) - 1 */
/* e^x = 1 + 2x P(x^2)/( Q(x^2) - P(x^2) )
* -0.5 <= x <= 0.5
*/
const static double EP[3] = {
1.2617719307481059087798E-4,
3.0299440770744196129956E-2,
9.9999999999999999991025E-1,
};
const static double EQ[4] = {
3.0019850513866445504159E-6,
2.5244834034968410419224E-3,
2.2726554820815502876593E-1,
2.0000000000000000000897E0,
};
double expm1(x)
double x;
{
double r, xx;
#ifdef NANS
if( isnan(x) )
return(x);
#endif
#ifdef INFINITIES
if( x == INFINITY )
return(INFINITY);
if( x == -INFINITY )
return(-1.0);
#endif
if( (x < -0.5) || (x > 0.5) )
return( exp(x) - 1.0 );
xx = x * x;
r = x * polevl( xx, EP, 2 );
r = r/( polevl( xx, EQ, 3 ) - r );
return (r + r);
}
/* cosm1(x) = cos(x) - 1 */
const static double coscof[7] = {
4.7377507964246204691685E-14,
-1.1470284843425359765671E-11,
2.0876754287081521758361E-9,
-2.7557319214999787979814E-7,
2.4801587301570552304991E-5,
-1.3888888888888872993737E-3,
4.1666666666666666609054E-2,
};
extern double PIO4;
double cosm1(x)
double x;
{
double xx;
if( (x < -PIO4) || (x > PIO4) )
return( cos(x) - 1.0 );
xx = x * x;
xx = -0.5*xx + xx * xx * polevl( xx, coscof, 6 );
return xx;
}

View File

@@ -0,0 +1,109 @@
# Double precision Cephes library
# Makefile for unix or GCC
CC = gcc
CFLAGS = -g -O2 -Wall -fno-builtin
AR = ar
RANLIB = ranlib
INCS = mconf.h
AS = as
OBJS = acosh.o airy.o asin.o asinh.o atan.o atanh.o bdtr.o beta.o \
btdtr.o cbrt.o chbevl.o chdtr.o clog.o cmplx.o const.o \
cosh.o dawsn.o drand.o ellie.o ellik.o ellpe.o ellpj.o ellpk.o \
exp.o exp10.o exp2.o expn.o fabs.o fac.o fdtr.o \
fresnl.o gamma.o gdtr.o hyp2f1.o hyperg.o i0.o i1.o igami.o \
incbet.o incbi.o igam.o isnan.o iv.o j0.o j1.o jn.o jv.o k0.o k1.o \
kn.o log.o log2.o log10.o lrand.o nbdtr.o ndtr.o ndtri.o pdtr.o \
polevl.o polmisc.o polyn.o pow.o powi.o psi.o rgamma.o round.o \
shichi.o sici.o sin.o sindg.o sinh.o spence.o stdtr.o struve.o \
tan.o tandg.o tanh.o unity.o yn.o zeta.o zetac.o \
sqrt.o floor.o setprec.o mtherr.o
all: libmd.a mtst dtestvec dcalc paranoia # stamp-timing
stamp-timing: libmd.a mtst time-it
time-it "mtst > /dev/null"
touch stamp-timing
time-it: time-it.o
$(CC) -o time-it time-it.o
time-it.o: time-it.c
$(CC) -O2 -c time-it.c
dcalc: dcalc.o libmd.a
$(CC) -o dcalc dcalc.o libmd.a
# aout2exe mtst
mtst: mtst.o libmd.a
$(CC) -v -o mtst mtst.o libmd.a
# gcc -Wl,-verbose -b i486-linuxaout -v -o mtst mtst.o libmd.a
# coff2exe mtst
mtst.o: mtst.c
$(CC) -O2 -Wall -c mtst.c
dtestvec: dtestvec.o libmd.a
$(CC) -o dtestvec dtestvec.o libmd.a
dtestvec.o: dtestvec.c
$(CC) -g -c dtestvec.c
paranoia: paranoia.o setprec.o libmd.a
$(CC) -o paranoia paranoia.o setprec.o libmd.a
paranoia.o: paranoia.c
$(CC) $(CFLAGS) -c paranoia.c
libmd.a: $(OBJS) $(INCS)
# for real Unix:
$(AR) rv libmd.a $(OBJS)
# for djgcc MSDOS:
# >libmd.rf -rv libmd.a $(OBJS)
# $(AR) @libmd.rf
$(RANLIB) libmd.a
# If the following are all commented out, the C versions
# will be used by default.
# IBM PC:
#sqrt.o: sqrt.387
# $(AS) -o sqrt.o sqrt.387
#
#floor.o: floor.387
# $(AS) -o floor.o floor.387
#
#setprec.o: setprec.387
# $(AS) -o setprec.o setprec.387
# ELF versions for linux (no underscores)
sqrt.o: sqrtelf.387
$(AS) -o sqrt.o sqrtelf.387
#floor.o: floorelf.387
# $(AS) -o floor.o floorelf.387
setprec.o: setprelf.387
$(AS) -o setprec.o setprelf.387
# Motorola 68881. Caution, subroutine return conventions vary.
#sqrt.o: sqrt.688
# $(AS) -o sqrt.o sqrt.688
#
#setprec.o: setprec.688
# $(AS) -o setprec.o setprec.688
# SPARC:
#sqrt.o: sqrt.spa
# $(AS) -o sqrt.o sqrt.spa
clean:
rm -f *.o
rm -f mtst
rm -f paranoia
rm -f dcalc
rm -f libmd.a
rm -f time-it
rm -f dtestvec

View File

@@ -0,0 +1,336 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* Common low-level device handling (Events, IO buffers)
* ----------------------------------------------------------------------------
*/
#include "jsdevices.h"
#include "jsparse.h"
#include "jsinteractive.h"
#ifdef LINUX
#include <signal.h>
#endif//LINUX
#ifdef USE_TRIGGER
#include "trigger.h"
#endif
#ifdef USE_CC3000
#include "board_spi.h"
#endif
// ----------------------------------------------------------------------------
// BUFFERS
// ----------------------------------------------------------------------------
// DATA TRANSMIT BUFFER
typedef struct {
IOEventFlags flags; // Where this data should be transmitted
unsigned char data; // data to transmit
} PACKED_FLAGS TxBufferItem;
TxBufferItem txBuffer[TXBUFFERMASK+1];
volatile unsigned char txHead=0, txTail=0;
// ----------------------------------------------------------------------------
// Queue a character for transmission
void jshTransmit(IOEventFlags device, unsigned char data) {
#ifdef RT_USING_JS
rt_device_write(rt_console_get_device(), 0, &data, 1);
#else
#ifndef LINUX
#ifdef USB
if (device==EV_USBSERIAL && !jshIsUSBSERIALConnected()) {
jshTransmitClearDevice(EV_USBSERIAL); // clear out stuff already waiting
return;
}
#endif
if (device==EV_NONE) return;
unsigned char txHeadNext = (txHead+1)&TXBUFFERMASK;
if (txHeadNext==txTail) {
jsiSetBusy(BUSY_TRANSMIT, true);
while (txHeadNext==txTail) {
// wait for send to finish as buffer is about to overflow
#ifdef USB
// just in case USB was unplugged while we were waiting!
if (!jshIsUSBSERIALConnected()) jshTransmitClearDevice(EV_USBSERIAL);
#endif
}
jsiSetBusy(BUSY_TRANSMIT, false);
}
txBuffer[txHead].flags = device;
txBuffer[txHead].data = (char)data;
txHead = txHeadNext;
jshUSARTKick(device); // set up interrupts if required
#else // if PC, just put to stdout
if (device==DEFAULT_CONSOLE_DEVICE) {
fputc(data, stdout);
fflush(stdout);
}
#endif
#endif
}
// Try and get a character for transmission - could just return -1 if nothing
int jshGetCharToTransmit(IOEventFlags device) {
unsigned char ptr = txTail;
while (txHead != ptr) {
if (IOEVENTFLAGS_GETTYPE(txBuffer[ptr].flags) == device) {
unsigned char data = txBuffer[ptr].data;
if (ptr != txTail) { // so we weren't right at the back of the queue
// we need to work back from ptr (until we hit tail), shifting everything forwards
unsigned char this = ptr;
unsigned char last = (unsigned char)((this+TXBUFFERMASK)&TXBUFFERMASK);
while (this!=txTail) { // if this==txTail, then last is before it, so stop here
txBuffer[this] = txBuffer[last];
this = last;
last = (unsigned char)((this+TXBUFFERMASK)&TXBUFFERMASK);
}
}
txTail = (unsigned char)((txTail+1)&TXBUFFERMASK); // advance the tail
return data; // return data
}
ptr = (unsigned char)((ptr+1)&TXBUFFERMASK);
}
return -1; // no data :(
}
void jshTransmitFlush() {
jsiSetBusy(BUSY_TRANSMIT, true);
while (jshHasTransmitData()) ; // wait for send to finish
jsiSetBusy(BUSY_TRANSMIT, false);
}
// Clear everything from a device
void jshTransmitClearDevice(IOEventFlags device) {
while (jshGetCharToTransmit(device)>=0);
}
bool jshHasTransmitData() {
#ifndef LINUX
return txHead != txTail;
#else
return false;
#endif
}
// ----------------------------------------------------------------------------
// IO EVENT BUFFER
IOEvent ioBuffer[IOBUFFERMASK+1];
volatile unsigned char ioHead=0, ioTail=0;
// ----------------------------------------------------------------------------
void jshIOEventOverflowed() {
// Error here - just light LED as we can't do much else right now
}
void jshPushIOCharEvent(IOEventFlags channel, char charData) {
if (charData==3 && channel==jsiGetConsoleDevice()) {
// Ctrl-C - force interrupt
#ifdef LINUX
raise(SIGINT);
#endif
jspSetInterrupted(true);
return;
}
if (DEVICE_IS_USART(channel) && jshGetEventsUsed() > IOBUFFER_XOFF)
jshSetFlowControlXON(channel, false);
// Check for existing buffer (we must have at least 2 in the queue to avoid dropping chars though!)
unsigned char nextTail = (unsigned char)((ioTail+1) & IOBUFFERMASK);
if (ioHead!=ioTail && ioHead!=nextTail) {
// we can do this because we only read in main loop, and we're in an interrupt here
unsigned char lastHead = (unsigned char)((ioHead+IOBUFFERMASK) & IOBUFFERMASK); // one behind head
if (IOEVENTFLAGS_GETTYPE(ioBuffer[lastHead].flags) == channel &&
IOEVENTFLAGS_GETCHARS(ioBuffer[lastHead].flags) < IOEVENT_MAXCHARS) {
// last event was for this event type, and it has chars left
unsigned char c = (unsigned char)IOEVENTFLAGS_GETCHARS(ioBuffer[lastHead].flags);
ioBuffer[lastHead].data.chars[c] = charData;
IOEVENTFLAGS_SETCHARS(ioBuffer[lastHead].flags, c+1);
return;
}
}
// Make new buffer
unsigned char nextHead = (unsigned char)((ioHead+1) & IOBUFFERMASK);
if (ioTail == nextHead) {
jshIOEventOverflowed();
return; // queue full - dump this event!
}
ioBuffer[ioHead].flags = channel;
IOEVENTFLAGS_SETCHARS(ioBuffer[ioHead].flags, 1);
ioBuffer[ioHead].data.chars[0] = charData;
ioHead = nextHead;
}
void jshPushIOWatchEvent(IOEventFlags channel) {
JsSysTime time = jshGetSystemTime();
bool state = jshGetWatchedPinState(channel);
/* // This is some simple debounce code - however it requires that the event
// is not taken out of ioBuffer by the main thread, which will require
// a bit of fiddling in jsinteractive.c. In fact it might be worth just
// doing debounce outside of the interrupt
if (true) { // debounce
// scan back and see if we have an event for this pin
unsigned char prevHead = ioHead;
while (prevHead!=ioTail && (IOEVENTFLAGS_GETTYPE(ioBuffer[prevHead].flags)!=channel))
prevHead = (unsigned char)((prevHead+IOBUFFERMASK) & IOBUFFERMASK); // step back
// if we have an event
if (prevHead!=ioTail && (IOEVENTFLAGS_GETTYPE(ioBuffer[prevHead].flags)==channel)) {
// just use it (with the same timestamp)...
ioBuffer[prevHead].flags = channel | (state?EV_EXTI_IS_HIGH:0);
return;
}
}*/
#ifdef USE_TRIGGER
if (trigHandleEXTI(channel | (state?EV_EXTI_IS_HIGH:0), time))
return;
#endif
#ifdef USE_CC3000
IOEvent event;
event.flags = channel;
if (!state && jshIsEventForPin(&event, WLAN_IRQ_PIN)) {
cc3000_irq_handler();
}
#endif
// Otherwise add this event
jshPushIOEvent(channel | (state?EV_EXTI_IS_HIGH:0), time);
}
void jshPushIOEvent(IOEventFlags channel, JsSysTime time) {
unsigned char nextHead = (unsigned char)((ioHead+1) & IOBUFFERMASK);
if (ioTail == nextHead) {
jshIOEventOverflowed();
return; // queue full - dump this event!
}
ioBuffer[ioHead].flags = channel;
ioBuffer[ioHead].data.time = time;
ioHead = nextHead;
}
// returns true on success
bool jshPopIOEvent(IOEvent *result) {
if (ioHead==ioTail) return false;
*result = ioBuffer[ioTail];
ioTail = (unsigned char)((ioTail+1) & IOBUFFERMASK);
return true;
}
bool jshHasEvents() {
return ioHead!=ioTail;
}
int jshGetEventsUsed() {
int spaceUsed = (ioHead >= ioTail) ? ((int)ioHead-(int)ioTail) : /*or rolled*/((int)ioHead+IOBUFFERMASK+1-(int)ioTail);
return spaceUsed;
}
bool jshHasEventSpaceForChars(int n) {
int spacesNeeded = 4 + (n/IOEVENT_MAXCHARS); // be sensible - leave a little spare
int spaceUsed = jshGetEventsUsed();
int spaceLeft = IOBUFFERMASK+1-spaceUsed;
return spaceLeft > spacesNeeded;
}
// ----------------------------------------------------------------------------
// DEVICES
const char *jshGetDeviceString(IOEventFlags device) {
switch (device) {
#ifdef USB
case EV_USBSERIAL: return "USB";
#endif
case EV_SERIAL1: return "Serial1";
case EV_SERIAL2: return "Serial2";
case EV_SERIAL3: return "Serial3";
#if USARTS>=4
case EV_SERIAL4: return "Serial4";
#endif
#if USARTS>=5
case EV_SERIAL5: return "Serial5";
#endif
#if USARTS>=6
case EV_SERIAL6: return "Serial6";
#endif
#if SPIS>=1
case EV_SPI1: return "SPI1";
#endif
#if SPIS>=2
case EV_SPI2: return "SPI2";
#endif
#if SPIS>=3
case EV_SPI3: return "SPI3";
#endif
#if I2CS>=1
case EV_I2C1: return "I2C1";
#endif
#if I2CS>=2
case EV_I2C2: return "I2C2";
#endif
#if I2CS>=3
case EV_I2C3: return "I2C3";
#endif
default: return "";
}
}
IOEventFlags jshFromDeviceString(const char *device) {
if (device[0]=='U') {
#ifdef USB
if (strcmp(device, "USB")==0) return EV_USBSERIAL;
#endif
}
else if (device[0]=='S') {
if (device[1]=='e' && device[2]=='r' && device[3]=='i' && device[4]=='a' && device[5]=='l') {
if (strcmp(device, "Serial1")==0) return EV_SERIAL1;
if (strcmp(device, "Serial2")==0) return EV_SERIAL2;
if (strcmp(device, "Serial3")==0) return EV_SERIAL3;
#if USARTS>=4
if (strcmp(device, "Serial4")==0) return EV_SERIAL4;
#endif
#if USARTS>=5
if (strcmp(device, "Serial5")==0) return EV_SERIAL5;
#endif
#if USARTS>=6
if (strcmp(device, "Serial6")==0) return EV_SERIAL6;
#endif
}
if (device[1]=='P' && device[2]=='I') {
#if SPIS>=1
if (strcmp(device, "SPI1")==0) return EV_SPI1;
#endif
#if SPIS>=2
if (strcmp(device, "SPI2")==0) return EV_SPI2;
#endif
#if SPIS>=3
if (strcmp(device, "SPI3")==0) return EV_SPI3;
#endif
}
}
else if (device[0]=='I' && device[1]=='2' && device[2]=='C') {
#if I2CS>=1
if (strcmp(device, "I2C1")==0) return EV_I2C1;
#endif
#if I2CS>=2
if (strcmp(device, "I2C2")==0) return EV_I2C2;
#endif
#if I2CS>=3
if (strcmp(device, "I2C3")==0) return EV_I2C3;
#endif
}
return EV_NONE;
}
/// Set whether the host should transmit or not
void jshSetFlowControlXON(IOEventFlags device, bool hostShouldTransmit) {
}

View File

@@ -0,0 +1,127 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* Common low-level device handling (Events, IO buffers)
* ----------------------------------------------------------------------------
*/
#ifndef JSDEVICES_H_
#define JSDEVICES_H_
#include "jsutils.h"
#include "platform_config.h"
typedef enum {
// device type
EV_NONE,
EV_EXTI0,
EV_EXTI1,
EV_EXTI2,
EV_EXTI3,
EV_EXTI4,
EV_EXTI5,
EV_EXTI6,
EV_EXTI7,
EV_EXTI8,
EV_EXTI9,
EV_EXTI10,
EV_EXTI11,
EV_EXTI12,
EV_EXTI13,
EV_EXTI14,
EV_EXTI15,
EV_EXTI_MAX = EV_EXTI15,
EV_USBSERIAL,
EV_SERIAL1,
EV_SERIAL2,
EV_SERIAL3,
EV_SERIAL4,
EV_SERIAL5,
EV_SERIAL6,
EV_SERIAL_MAX = EV_SERIAL6,
EV_SPI1,
EV_SPI2,
EV_SPI3,
EV_SPI_MAX = EV_SPI3,
EV_I2C1,
EV_I2C2,
EV_I2C3,
EV_I2C_MAX = EV_I2C3,
EV_DEVICE_MAX = EV_I2C_MAX,
// EV_DEVICE_MAX should not be >64 - see DEVICE_INITIALISED_FLAGS
// Also helps if we're under 32 so we can fit IOEventFlags into a byte
EV_TYPE_MASK = NEXT_POWER_2(EV_DEVICE_MAX) - 1,
EV_CHARS_MASK = 7 * NEXT_POWER_2(EV_DEVICE_MAX),
// -----------------------------------------
// if the pin we're watching is high, the handler sets this
EV_EXTI_IS_HIGH = NEXT_POWER_2(EV_DEVICE_MAX),
} PACKED_FLAGS IOEventFlags;
#define DEVICE_IS_USART(X) (((X)>=EV_USBSERIAL)&& ((X)<=EV_SERIAL_MAX))
#define DEVICE_IS_SPI(X) (((X)>=EV_SPI1) || ((X)<=EV_SPI_MAX))
#define DEVICE_IS_I2C(X) (((X)>=EV_I2C1) || ((X)<=EV_I2C_MAX))
#define DEVICE_IS_EXTI(X) (((X)>=EV_EXTI0) || ((X)<=EV_EXTI_MAX))
#define IOEVENTFLAGS_GETTYPE(X) ((X)&EV_TYPE_MASK)
#define IOEVENTFLAGS_GETCHARS(X) ((((X)&EV_CHARS_MASK)>>5)+1)
#define IOEVENTFLAGS_SETCHARS(X,CHARS) ((X)=(((X)&(IOEventFlags)~EV_CHARS_MASK) | (((CHARS)-1)<<5)))
#define IOEVENT_MAXCHARS 8
typedef union {
JsSysTime time; // time event occurred
char chars[IOEVENT_MAXCHARS];
} PACKED_FLAGS IOEventData;
// IO Events - these happen when a pin changes
typedef struct IOEvent {
IOEventFlags flags; // where this came from, and # of chars in it
IOEventData data;
} PACKED_FLAGS IOEvent;
void jshPushIOEvent(IOEventFlags channel, JsSysTime time);
void jshPushIOWatchEvent(IOEventFlags channel); // push an even when a pin changes state
/// Push a single character event (for example USART RX)
void jshPushIOCharEvent(IOEventFlags channel, char charData);
/// Push many character events at once (for example USB RX)
static inline void jshPushIOCharEvents(IOEventFlags channel, char *data, unsigned int count) {
// TODO: optimise me!
unsigned int i;
for (i=0;i<count;i++) jshPushIOCharEvent(channel, data[i]);
}
bool jshPopIOEvent(IOEvent *result); ///< returns true on success
/// Do we have any events pending? Will jshPopIOEvent return true?
bool jshHasEvents();
/// How many event blocks are left? compare this to IOBUFFERMASK
int jshGetEventsUsed();
/// Do we have enough space for N characters?
bool jshHasEventSpaceForChars(int n);
const char *jshGetDeviceString(IOEventFlags device);
IOEventFlags jshFromDeviceString(const char *device);
// ----------------------------------------------------------------------------
// DATA TRANSMIT BUFFER
/// Queue a character for transmission
void jshTransmit(IOEventFlags device, unsigned char data);
/// Wait for transmit to finish
void jshTransmitFlush();
/// Clear everything from a device
void jshTransmitClearDevice(IOEventFlags device);
/// Do we have anything we need to send?
bool jshHasTransmitData();
/// Try and get a character for transmission - could just return -1 if nothing
int jshGetCharToTransmit(IOEventFlags device);
/// Set whether the host should transmit or not
void jshSetFlowControlXON(IOEventFlags device, bool hostShouldTransmit);
#endif /* JSDEVICES_H_ */

View File

@@ -0,0 +1,223 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* Hardware interface Layer
* NOTE: The definitions of these functions are inside:
* targets/{target}/jshardware.c
* ----------------------------------------------------------------------------
*/
#ifndef JSHARDWARE_H_
#define JSHARDWARE_H_
#include "jsutils.h"
#include "jsvar.h"
#include "jsdevices.h"
#include "jspin.h"
#ifndef LINUX
#include "jspininfo.h"
#else
#include <inttypes.h>
#endif
void jshInit();
void jshKill();
void jshIdle(); // stuff to do on idle
/// Get this IC's serial number. Passed max # of chars and a pointer to write to. Returns # of chars
int jshGetSerialNumber(unsigned char *data, int maxChars);
bool jshIsUSBSERIALConnected(); // is the serial device connected?
/// Get the system time (in ticks)
JsSysTime jshGetSystemTime();
/// Convert a time in Milliseconds to one in ticks
JsSysTime jshGetTimeFromMilliseconds(JsVarFloat ms);
/// Convert ticks to a time in Milliseconds
JsVarFloat jshGetMillisecondsFromTime(JsSysTime time);
// software IO functions...
void jshInterruptOff();
void jshInterruptOn();
void jshDelayMicroseconds(int microsec);
void jshPinSetValue(Pin pin, bool value);
bool jshPinGetValue(Pin pin);
// ------
typedef enum {
JSHPINSTATE_UNDEFINED,
JSHPINSTATE_GPIO_OUT,
JSHPINSTATE_GPIO_OUT_OPENDRAIN,
JSHPINSTATE_GPIO_IN,
JSHPINSTATE_GPIO_IN_PULLUP,
JSHPINSTATE_GPIO_IN_PULLDOWN,
JSHPINSTATE_ADC_IN,
JSHPINSTATE_AF_OUT,
JSHPINSTATE_USART_IN,
JSHPINSTATE_USART_OUT,
JSHPINSTATE_DAC_OUT,
JSHPINSTATE_I2C,
JSHPINSTATE_MASK = NEXT_POWER_2(JSHPINSTATE_I2C)-1,
JSHPINSTATE_PIN_IS_ON = JSHPINSTATE_MASK+1,
} PACKED_FLAGS JshPinState;
#define JSHPINSTATE_IS_OUTPUT(state) ( \
state==JSHPINSTATE_GPIO_OUT || \
state==JSHPINSTATE_GPIO_OUT_OPENDRAIN || \
state==JSHPINSTATE_AF_OUT || \
state==JSHPINSTATE_USART_OUT || \
state==JSHPINSTATE_DAC_OUT || \
state==JSHPINSTATE_I2C \
)
/// Is the pin state manual (has the user asked us explicitly to change it?)
bool jshGetPinStateIsManual(Pin pin);
/// Is the pin state manual (has the user asked us explicitly to change it?)
void jshSetPinStateIsManual(Pin pin, bool manual);
/// Set the pin state
void jshPinSetState(Pin pin, JshPinState state);
/** Get the pin state (only accurate for simple IO - won't return JSHPINSTATE_USART_OUT for instance).
* Note that you should use JSHPINSTATE_MASK as other flags may have been added */
JshPinState jshPinGetState(Pin pin);
bool jshPinInput(Pin pin);
JsVarFloat jshPinAnalog(Pin pin);
void jshPinOutput(Pin pin, bool value);
void jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq); // if freq<=0, the default is used
void jshPinPulse(Pin pin, bool value, JsVarFloat time);
void jshPinWatch(Pin pin, bool shouldWatch);
/// returns false if timer queue was full...
bool jshPinOutputAtTime(JsSysTime time, Pin pin, bool value);
/** Check the pin associated with this EXTI - return true if it is a 1 */
bool jshGetWatchedPinState(IOEventFlags device);
bool jshIsEventForPin(IOEvent *event, Pin pin);
/** Is the given device initialised? */
bool jshIsDeviceInitialised(IOEventFlags device);
#define DEFAULT_BAUD_RATE 9600
#define DEFAULT_BYTESIZE 8
#define DEFAULT_PARITY 0
#define DEFAULT_STOPBITS 1
typedef struct {
int baudRate; // FIXME uint32_t ???
Pin pinRX;
Pin pinTX;
unsigned char bytesize;
unsigned char parity;
unsigned char stopbits;
} PACKED_FLAGS JshUSARTInfo;
static inline void jshUSARTInitInfo(JshUSARTInfo *inf) {
inf->baudRate = DEFAULT_BAUD_RATE;
inf->pinRX = PIN_UNDEFINED;
inf->pinTX = PIN_UNDEFINED;
inf->bytesize = DEFAULT_BYTESIZE;
inf->parity = DEFAULT_PARITY; // PARITY_NONE = 0, PARITY_ODD = 1, PARITY_EVEN = 2 FIXME: enum?
inf->stopbits = DEFAULT_STOPBITS;
}
/** Set up a UART, if pins are -1 they will be guessed */
void jshUSARTSetup(IOEventFlags device, JshUSARTInfo *inf);
/** Kick a device into action (if required). For instance we may need
* to set up interrupts */
void jshUSARTKick(IOEventFlags device);
typedef enum {
SPIF_CPHA = 1,
SPIF_CPOL = 2,
SPIF_SPI_MODE_0 = 0,
SPIF_SPI_MODE_1 = SPIF_CPHA,
SPIF_SPI_MODE_2 = SPIF_CPOL,
SPIF_SPI_MODE_3 = SPIF_CPHA | SPIF_CPOL,
/* Mode CPOL CPHA
0 0 0
1 0 1
2 1 0
3 1 1
*/
} PACKED_FLAGS JshSPIFlags;
typedef struct {
int baudRate;
Pin pinSCK;
Pin pinMISO;
Pin pinMOSI;
unsigned char spiMode;
} PACKED_FLAGS JshSPIInfo;
static inline void jshSPIInitInfo(JshSPIInfo *inf) {
inf->baudRate = 1000000;
inf->pinSCK = PIN_UNDEFINED;
inf->pinMISO = PIN_UNDEFINED;
inf->pinMOSI = PIN_UNDEFINED;
inf->spiMode = SPIF_SPI_MODE_0;
}
/** Set up SPI, if pins are -1 they will be guessed */
void jshSPISetup(IOEventFlags device, JshSPIInfo *inf);
/** Send data through the given SPI device (if data>=0), and return the result
* of the previous send (or -1). If data<0, no data is sent and the function
* waits for data to be returned */
int jshSPISend(IOEventFlags device, int data);
/** Send 16 bit data through the given SPI device. */
void jshSPISend16(IOEventFlags device, int data);
/** Set whether to send 16 bits or 8 over SPI */
void jshSPISet16(IOEventFlags device, bool is16);
typedef struct {
Pin pinSCL;
Pin pinSDA;
char slaveAddr; // or -1 if it is master!
// speed? 100khz std
// timeout?
} PACKED_FLAGS JshI2CInfo;
static inline void jshI2CInitInfo(JshI2CInfo *inf) {
inf->pinSCL = PIN_UNDEFINED;
inf->pinSDA = PIN_UNDEFINED;
inf->slaveAddr = (char)-1; // master
}
/** Set up I2C, if pins are -1 they will be guessed */
void jshI2CSetup(IOEventFlags device, JshI2CInfo *inf);
/** Addresses are 7 bit - that is, between 0 and 0x7F */
void jshI2CWrite(IOEventFlags device, unsigned char address, int nBytes, const unsigned char *data);
void jshI2CRead(IOEventFlags device, unsigned char address, int nBytes, unsigned char *data);
/// Save contents of JsVars into Flash
void jshSaveToFlash();
/// Load contents of JsVars from Flash
void jshLoadFromFlash();
/// Returns true if flash contains something useful
bool jshFlashContainsCode();
/// Enter simple sleep mode (can be woken up by interrupts). Returns true on success
bool jshSleep(JsSysTime timeUntilWake);
// ---------------------------------------------- LOW LEVEL
#ifdef ARM
// ----------------------------------------------------------------------------
// SYSTICK
// On SYSTick interrupt, call this
void jshDoSysTick();
#ifdef USB
// Kick the USB SysTick watchdog - we need this to see if we have disconnected or not
void jshKickUSBWatchdog();
#endif
#endif // ARM
#endif /* JSHARDWARE_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,105 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* Interactive Shell implementation
* ----------------------------------------------------------------------------
*/
#ifndef JSINTERACTIVE_H_
#define JSINTERACTIVE_H_
#include "jsparse.h"
#include "jshardware.h"
#define JSI_WATCHES_NAME ">watches"
#define JSI_TIMERS_NAME ">timers"
#define JSI_HISTORY_NAME ">history"
#define JSI_INIT_CODE_NAME ">init"
#define JSI_ONINIT_NAME "onInit"
/// autoLoad = do we load the current state if it exists?
void jsiInit(bool autoLoad);
void jsiKill();
void jsiLoop();
/// Tries to get rid of some memory (by clearing command history). Returns true if it got rid of something, false if it didn't.
bool jsiFreeMoreMemory();
bool jsiHasTimers(); // are there timers still left to run?
JsParse *jsiGetParser();
/// Queue up callbacks for other things (touchscreen? network?)
void jsiQueueObjectCallbacks(JsVar *object, const char *callbackName, JsVar *arg0, JsVar *arg1);
IOEventFlags jsiGetDeviceFromClass(JsVar *deviceClass);
JsVar *jsiGetClassNameFromDevice(IOEventFlags device);
/// Change the console to a new location
void jsiSetConsoleDevice(IOEventFlags device);
/// Get the device that the console is currently on
IOEventFlags jsiGetConsoleDevice();
/// Transmit a byte
void jsiConsolePrintChar(char data);
/// Transmit a string
void jsiConsolePrint(const char *str);
/// Write the formatted string to the console (see vcbprintf)
void jsiConsolePrintf(const char *fmt, ...);
/// Print the contents of a string var - directly
void jsiConsolePrintStringVar(JsVar *v);
/// Transmit an integer
void jsiConsolePrintInt(JsVarInt d);
/// Transmit a position in the lexer (for reporting errors)
void jsiConsolePrintPosition(struct JsLex *lex, int tokenPos);
/// Transmit the current line, along with a marker of where the error was (for reporting errors)
void jsiConsolePrintTokenLineMarker(struct JsLex *lex, int tokenPos);
/// Print the contents of a string var to a device - directly
void jsiTransmitStringVar(IOEventFlags device, JsVar *v);
/// If the input line was shown in the console, remove it
void jsiConsoleRemoveInputLine();
/// Change what is in the inputline into something else (and update the console)
void jsiReplaceInputLine(JsVar *newLine);
/// Flags for jsiSetBusy - THESE SHOULD BE 2^N
typedef enum {
BUSY_INTERACTIVE = 1,
BUSY_TRANSMIT = 2,
// ??? = 4
} JsiBusyDevice;
/// Shows a busy indicator, if one is set up
void jsiSetBusy(JsiBusyDevice device, bool isBusy);
/// Shows a sleep indicator, if one is set up
void jsiSetSleep(bool isSleep);
// for jswrap_interactive/io.c ----------------------------------------------------
typedef enum {
TODO_NOTHING = 0,
TODO_FLASH_SAVE = 1,
TODO_FLASH_LOAD = 2,
TODO_RESET = 4,
} TODOFlags;
#define USART_CALLBACK_NAME "_callback"
#define USART_BAUDRATE_NAME "_baudrate"
#define DEVICE_OPTIONS_NAME "_options"
extern Pin pinBusyIndicator;
extern Pin pinSleepIndicator;
extern bool echo;
extern bool allowDeepSleep;
void jsiDumpState();
void jsiSetTodo(TODOFlags newTodo);
#define TIMER_MIN_INTERVAL 0.1 // in milliseconds
extern JsVarRef timerArray; // Linked List of timers to check and run
extern JsVarRef watchArray; // Linked List of input watches to check and run
// end for jswrap_interactive/io.c ------------------------------------------------
#endif /* JSINTERACTIVE_H_ */

501
components/external/espruino/src/jslex.c vendored Normal file
View File

@@ -0,0 +1,501 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* Lexer (convert JsVar strings into a series of tokens)
* ----------------------------------------------------------------------------
*/
#include "jslex.h"
void jslSeek(JsLex *lex, JslCharPos seekToChar) {
jsvStringIteratorFree(&lex->it);
jsvStringIteratorNew(&lex->it, lex->sourceVar, seekToChar);
}
void NO_INLINE jslGetNextCh(JsLex *lex) {
lex->currCh = lex->nextCh;
lex->nextCh = jsvStringIteratorGetChar(&lex->it);
jsvStringIteratorNextInline(&lex->it);
}
static inline void jslTokenAppendChar(JsLex *lex, char ch) {
/* Add character to buffer but check it isn't too big.
* Also Leave ONE character at the end for null termination */
if (lex->tokenl < JSLEX_MAX_TOKEN_LENGTH-1) {
lex->token[lex->tokenl++] = ch;
}
#ifdef DEBUG
else {
jsWarnAt("Token name is too long! skipping character", lex, lex->tokenStart);
}
#endif
}
static bool jslIsToken(JsLex *lex, const char *token, int startOffset) {
int i;
for (i=startOffset;i<lex->tokenl;i++) {
if (lex->token[i]!=token[i]) return false;
// if token is smaller than lex->token, there will be a null char
// which will be different from the token
}
return token[lex->tokenl] == 0; // only match if token ends now
}
void jslGetNextToken(JsLex *lex) {
lex->tk = LEX_EOF;
lex->tokenl = 0; // clear token string
if (lex->tokenValue) {
jsvUnLock(lex->tokenValue);
lex->tokenValue = 0;
}
while (lex->currCh && isWhitespace(lex->currCh)) jslGetNextCh(lex);
// newline comments
if (lex->currCh=='/' && lex->nextCh=='/') {
while (lex->currCh && lex->currCh!='\n') jslGetNextCh(lex);
jslGetNextCh(lex);
jslGetNextToken(lex);
return;
}
// block comments
if (lex->currCh=='/' && lex->nextCh=='*') {
while (lex->currCh && !(lex->currCh=='*' && lex->nextCh=='/'))
jslGetNextCh(lex);
if (!lex->currCh) {
lex->tk = LEX_UNFINISHED_COMMENT;
return; /* an unfinished multi-line comment. When in interactive console,
detect this and make sure we accept new lines */
}
jslGetNextCh(lex);
jslGetNextCh(lex);
jslGetNextToken(lex);
return;
}
// record beginning of this token
lex->tokenLastStart = lex->tokenStart;
lex->tokenStart = (JslCharPos)(lex->it.index-2);
// tokens
if (isAlpha(lex->currCh) || lex->currCh=='$') { // IDs
while (isAlpha(lex->currCh) || isNumeric(lex->currCh) || lex->currCh=='$') {
jslTokenAppendChar(lex, lex->currCh);
jslGetNextCh(lex);
}
lex->tk = LEX_ID;
// We do fancy stuff here to reduce number of compares (hopefully GCC creates a jump table)
switch (lex->token[0]) {
case 'b': if (jslIsToken(lex,"break", 1)) lex->tk = LEX_R_BREAK;
break;
case 'c': if (jslIsToken(lex,"case", 1)) lex->tk = LEX_R_CASE;
else if (jslIsToken(lex,"continue", 1)) lex->tk = LEX_R_CONTINUE;
break;
case 'd': if (jslIsToken(lex,"default", 1)) lex->tk = LEX_R_DEFAULT;
else if (jslIsToken(lex,"do", 1)) lex->tk = LEX_R_DO;
break;
case 'e': if (jslIsToken(lex,"else", 1)) lex->tk = LEX_R_ELSE;
break;
case 'f': if (jslIsToken(lex,"false", 1)) lex->tk = LEX_R_FALSE;
else if (jslIsToken(lex,"for", 1)) lex->tk = LEX_R_FOR;
else if (jslIsToken(lex,"function", 1)) lex->tk = LEX_R_FUNCTION;
break;
case 'i': if (jslIsToken(lex,"if", 1)) lex->tk = LEX_R_IF;
else if (jslIsToken(lex,"in", 1)) lex->tk = LEX_R_IN;
else if (jslIsToken(lex,"instanceof", 1)) lex->tk = LEX_R_INSTANCEOF;
break;
case 'n': if (jslIsToken(lex,"new", 1)) lex->tk = LEX_R_NEW;
else if (jslIsToken(lex,"null", 1)) lex->tk = LEX_R_NULL;
break;
case 'r': if (jslIsToken(lex,"return", 1)) lex->tk = LEX_R_RETURN;
break;
case 's': if (jslIsToken(lex,"switch", 1)) lex->tk = LEX_R_SWITCH;
break;
case 't': if (jslIsToken(lex,"this", 1)) lex->tk = LEX_R_THIS;
else if (jslIsToken(lex,"true", 1)) lex->tk = LEX_R_TRUE;
else if (jslIsToken(lex,"typeof", 1)) lex->tk = LEX_R_TYPEOF;
break;
case 'u': if (jslIsToken(lex,"undefined", 1)) lex->tk = LEX_R_UNDEFINED;
break;
case 'w': if (jslIsToken(lex,"while", 1)) lex->tk = LEX_R_WHILE;
break;
case 'v': if (jslIsToken(lex,"var", 1)) lex->tk = LEX_R_VAR;
else if (jslIsToken(lex,"void", 1)) lex->tk = LEX_R_VOID;
break;
default: break;
}
} else if (isNumeric(lex->currCh)) { // Numbers
// TODO: check numbers aren't the wrong format
bool canBeFloating = true;
if (lex->currCh=='0') {
jslTokenAppendChar(lex, lex->currCh);
jslGetNextCh(lex);
}
if ((lex->currCh=='x' || lex->currCh=='X') ||
(lex->currCh=='b' || lex->currCh=='B') ||
(lex->currCh=='o' || lex->currCh=='O')) {
canBeFloating = false;
jslTokenAppendChar(lex, lex->currCh); jslGetNextCh(lex);
}
lex->tk = LEX_INT;
while (isNumeric(lex->currCh) || (!canBeFloating && isHexadecimal(lex->currCh))) {
jslTokenAppendChar(lex, lex->currCh);
jslGetNextCh(lex);
}
if (canBeFloating && lex->currCh=='.') {
lex->tk = LEX_FLOAT;
jslTokenAppendChar(lex, '.');
jslGetNextCh(lex);
while (isNumeric(lex->currCh)) {
jslTokenAppendChar(lex, lex->currCh);
jslGetNextCh(lex);
}
}
// do fancy e-style floating point
if (canBeFloating && (lex->currCh=='e'||lex->currCh=='E')) {
lex->tk = LEX_FLOAT;
jslTokenAppendChar(lex, lex->currCh); jslGetNextCh(lex);
if (lex->currCh=='-' || lex->currCh=='+') { jslTokenAppendChar(lex, lex->currCh); jslGetNextCh(lex); }
while (isNumeric(lex->currCh)) {
jslTokenAppendChar(lex, lex->currCh); jslGetNextCh(lex);
}
}
} else if (lex->currCh=='"' || lex->currCh=='\'') {
char delim = lex->currCh;
lex->tokenValue = jsvNewFromEmptyString();
// strings...
jslGetNextCh(lex);
while (lex->currCh && lex->currCh!=delim) {
if (lex->currCh == '\\') {
jslGetNextCh(lex);
char ch = lex->currCh;
switch (lex->currCh) {
case 'n' : ch = '\n'; jslGetNextCh(lex); break;
case 'a' : ch = '\a'; jslGetNextCh(lex); break;
case 'r' : ch = '\r'; jslGetNextCh(lex); break;
case 't' : ch = '\t'; jslGetNextCh(lex); break;
case 'x' : { // hex digits
char buf[5] = "0x??";
jslGetNextCh(lex);
buf[2] = lex->currCh; jslGetNextCh(lex);
buf[3] = lex->currCh; jslGetNextCh(lex);
ch = (char)stringToInt(buf);
} break;
default:
if (lex->currCh>='0' && lex->currCh<='7') {
// octal digits
char buf[5] = "0";
buf[1] = lex->currCh;
int n=2;
jslGetNextCh(lex);
if (lex->currCh>='0' && lex->currCh<='7') {
buf[n++] = lex->currCh; jslGetNextCh(lex);
if (lex->currCh>='0' && lex->currCh<='7') {
buf[n++] = lex->currCh; jslGetNextCh(lex);
}
}
buf[n]=0;
ch = (char)stringToInt(buf);
} else {
// for anything else, just push the character through
jslGetNextCh(lex);
}
break;
}
if (lex->tokenValue) {
jslTokenAppendChar(lex, ch);
jsvAppendCharacter(lex->tokenValue, ch);
}
} else {
if (lex->tokenValue) {
jslTokenAppendChar(lex, lex->currCh);
jsvAppendCharacter(lex->tokenValue, lex->currCh);
}
jslGetNextCh(lex);
}
}
jslGetNextCh(lex);
lex->tk = LEX_STR;
} else {
// single chars
lex->tk = lex->currCh;
jslGetNextCh(lex);
if (lex->tk=='=' && lex->currCh=='=') { // ==
lex->tk = LEX_EQUAL;
jslGetNextCh(lex);
if (lex->currCh=='=') { // ===
lex->tk = LEX_TYPEEQUAL;
jslGetNextCh(lex);
}
} else if (lex->tk=='!' && lex->currCh=='=') { // !=
lex->tk = LEX_NEQUAL;
jslGetNextCh(lex);
if (lex->currCh=='=') { // !==
lex->tk = LEX_NTYPEEQUAL;
jslGetNextCh(lex);
}
} else if (lex->tk=='<') {
if (lex->currCh=='=') {
lex->tk = LEX_LEQUAL;
jslGetNextCh(lex);
} else if (lex->currCh=='<') {
lex->tk = LEX_LSHIFT;
jslGetNextCh(lex);
if (lex->currCh=='=') { // <<=
lex->tk = LEX_LSHIFTEQUAL;
jslGetNextCh(lex);
}
}
} else if (lex->tk=='>') {
if (lex->currCh=='=') {
lex->tk = LEX_GEQUAL;
jslGetNextCh(lex);
} else if (lex->currCh=='>') {
lex->tk = LEX_RSHIFT;
jslGetNextCh(lex);
if (lex->currCh=='=') { // >>=
lex->tk = LEX_RSHIFTEQUAL;
jslGetNextCh(lex);
} else if (lex->currCh=='>') { // >>>
jslGetNextCh(lex);
if (lex->currCh=='=') { // >>>=
lex->tk = LEX_RSHIFTUNSIGNEDEQUAL;
jslGetNextCh(lex);
} else {
lex->tk = LEX_RSHIFTUNSIGNED;
}
}
}
} else if (lex->tk=='+') {
if (lex->currCh=='=') {
lex->tk = LEX_PLUSEQUAL;
jslGetNextCh(lex);
} else if (lex->currCh=='+') {
lex->tk = LEX_PLUSPLUS;
jslGetNextCh(lex);
}
} else if (lex->tk=='-') {
if (lex->currCh=='=') {
lex->tk = LEX_MINUSEQUAL;
jslGetNextCh(lex);
} else if (lex->currCh=='-') {
lex->tk = LEX_MINUSMINUS;
jslGetNextCh(lex);
}
} else if (lex->tk=='&') {
if (lex->currCh=='=') {
lex->tk = LEX_ANDEQUAL;
jslGetNextCh(lex);
} else if (lex->currCh=='&') {
lex->tk = LEX_ANDAND;
jslGetNextCh(lex);
}
} else if (lex->tk=='|') {
if (lex->currCh=='=') {
lex->tk = LEX_OREQUAL;
jslGetNextCh(lex);
} else if (lex->tk=='|' && lex->currCh=='|') {
lex->tk = LEX_OROR;
jslGetNextCh(lex);
}
} else if (lex->tk=='^' && lex->currCh=='=') {
lex->tk = LEX_XOREQUAL;
jslGetNextCh(lex);
} else if (lex->tk=='*' && lex->currCh=='=') {
lex->tk = LEX_MULEQUAL;
jslGetNextCh(lex);
} else if (lex->tk=='/' && lex->currCh=='=') {
lex->tk = LEX_DIVEQUAL;
jslGetNextCh(lex);
} else if (lex->tk=='%' && lex->currCh=='=') {
lex->tk = LEX_MODEQUAL;
jslGetNextCh(lex);
}
}
/* This isn't quite right yet */
lex->tokenLastEnd = lex->tokenEnd;
lex->tokenEnd = (JslCharPos)(lex->it.index-3)/*because of nextCh/currCh/etc */;
}
static inline void jslPreload(JsLex *lex) {
// set up..
jslGetNextCh(lex);
jslGetNextCh(lex);
jslGetNextToken(lex);
}
void jslInit(JsLex *lex, JsVar *var) {
lex->sourceVar = jsvLockAgain(var);
// reset stuff
lex->tk = 0;
lex->tokenStart = 0;
lex->tokenEnd = 0;
lex->tokenLastStart = 0;
lex->tokenLastEnd = 0;
lex->tokenl = 0;
lex->tokenValue = 0;
// set up iterator
jsvStringIteratorNew(&lex->it, lex->sourceVar, 0);
jslPreload(lex);
}
void jslKill(JsLex *lex) {
lex->tk = LEX_EOF; // safety ;)
jsvStringIteratorFree(&lex->it);
if (lex->tokenValue) {
jsvUnLock(lex->tokenValue);
lex->tokenValue = 0;
}
jsvUnLock(lex->sourceVar);
}
void jslSeekTo(JsLex *lex, JslCharPos seekToChar) {
jslSeek(lex, seekToChar);
jslPreload(lex);
}
void jslReset(JsLex *lex) {
jslSeekTo(lex, 0);
}
void jslTokenAsString(int token, char *str, size_t len) {
// see JS_ERROR_TOKEN_BUF_SIZE
if (token>32 && token<128) {
assert(len>=4);
str[0] = '\'';
str[1] = (char)token;
str[2] = '\'';
str[3] = 0;
return;
}
switch (token) {
case LEX_EOF : strncpy(str, "EOF", len); return;
case LEX_ID : strncpy(str, "ID", len); return;
case LEX_INT : strncpy(str, "INT", len); return;
case LEX_FLOAT : strncpy(str, "FLOAT", len); return;
case LEX_STR : strncpy(str, "STRING", len); return;
}
if (token>=LEX_EQUAL && token<LEX_R_LIST_END) {
const char tokenNames[] =
/* LEX_EQUAL : */ "==\0"
/* LEX_TYPEEQUAL : */ "===\0"
/* LEX_NEQUAL : */ "!=\0"
/* LEX_NTYPEEQUAL : */ "!==\0"
/* LEX_LEQUAL : */ "<=\0"
/* LEX_LSHIFT : */ "<<\0"
/* LEX_LSHIFTEQUAL : */ "<<=\0"
/* LEX_GEQUAL : */ ">=\0"
/* LEX_RSHIFT : */ ">>\0"
/* LEX_RSHIFTUNSIGNED */ ">>>\0"
/* LEX_RSHIFTEQUAL : */ ">>=\0"
/* LEX_RSHIFTUNSIGNEDEQUAL */ ">>>=\0"
/* LEX_PLUSEQUAL : */ "+=\0"
/* LEX_MINUSEQUAL : */ "-=\0"
/* LEX_PLUSPLUS : */ "++\0"
/* LEX_MINUSMINUS */ "--\0"
/* LEX_MULEQUAL : */ "*=\0"
/* LEX_DIVEQUAL : */ "/=\0"
/* LEX_MODEQUAL : */ "%=\0"
/* LEX_ANDEQUAL : */ "&=\0"
/* LEX_ANDAND : */ "&&\0"
/* LEX_OREQUAL : */ "|=\0"
/* LEX_OROR : */ "||\0"
/* LEX_XOREQUAL : */ "^=\0"
// reserved words
/*LEX_R_IF : */ "if\0"
/*LEX_R_ELSE : */ "else\0"
/*LEX_R_DO : */ "do\0"
/*LEX_R_WHILE : */ "while\0"
/*LEX_R_FOR : */ "for\0"
/*LEX_R_BREAK : */ "return\0"
/*LEX_R_CONTINUE */ "continue\0"
/*LEX_R_FUNCTION */ "function\0"
/*LEX_R_RETURN */ "return\0"
/*LEX_R_VAR : */ "var\0"
/*LEX_R_THIS : */ "this\0"
/*LEX_R_TRUE : */ "true\0"
/*LEX_R_FALSE : */ "false\0"
/*LEX_R_NULL : */ "null\0"
/*LEX_R_UNDEFINED */ "undefined\0"
/*LEX_R_NEW : */ "new\0"
/*LEX_R_IN : */ "in\0"
/*LEX_R_INSTANCEOF */ "instanceof\0"
/*LEX_R_SWITCH */ "switch\0"
/*LEX_R_CASE */ "case\0"
/*LEX_R_DEFAULT */ "default\0"
/*LEX_R_TYPEOF : */ "typeof\0"
/*LEX_R_VOID : */ "void\0"
;
unsigned int p = 0;
int n = token-LEX_EQUAL;
while (n>0 && p<sizeof(tokenNames)) {
while (tokenNames[p] && p<sizeof(tokenNames)) p++;
p++; // skip the zero
n--; // next token
}
assert(n==0);
strncpy(str, &tokenNames[p], len);
return;
}
assert(len>=10);
strncpy(str, "?[",len);
itoa(token, &str[2], 10);
strncat(str, "]",len);
}
void jslGetTokenString(JsLex *lex, char *str, size_t len) {
if (lex->tk == LEX_ID) {
strncpy(str, "ID:", len);
strncat(str, jslGetTokenValueAsString(lex), len);
} else if (lex->tk == LEX_STR) {
strncpy(str, "String:'", len);
strncat(str, jslGetTokenValueAsString(lex), len);
strncat(str, "'", len);
} else
jslTokenAsString(lex->tk, str, len);
}
char *jslGetTokenValueAsString(JsLex *lex) {
assert(lex->tokenl < JSLEX_MAX_TOKEN_LENGTH);
lex->token[lex->tokenl] = 0; // add final null
return lex->token;
}
JsVar *jslGetTokenValueAsVar(JsLex *lex) {
if (lex->tokenValue) {
return jsvLockAgain(lex->tokenValue);
} else {
assert(lex->tokenl < JSLEX_MAX_TOKEN_LENGTH);
lex->token[lex->tokenl] = 0; // add final null
return jsvNewFromString(lex->token);
}
}
/// Match, and return true on success, false on failure
bool jslMatch(JsLex *lex, int expected_tk) {
if (lex->tk!=expected_tk) {
char buf[JS_ERROR_BUF_SIZE];
size_t bufpos = 0;
strncpy(&buf[bufpos], "Got ", JS_ERROR_BUF_SIZE-bufpos);
bufpos = strlen(buf);
jslGetTokenString(lex, &buf[bufpos], JS_ERROR_BUF_SIZE-bufpos);
bufpos = strlen(buf);
strncpy(&buf[bufpos], " expected ", JS_ERROR_BUF_SIZE-bufpos);
bufpos = strlen(buf);
jslTokenAsString(expected_tk, &buf[bufpos], JS_ERROR_BUF_SIZE-bufpos);
jsErrorAt(buf, lex, lex->tokenStart);
// Sod it, skip this token anyway - stops us looping
jslGetNextToken(lex);
return false;
}
jslGetNextToken(lex);
return true;
}

View File

@@ -0,0 +1,59 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* Lexer (convert JsVar strings into a series of tokens)
* ----------------------------------------------------------------------------
*/
#ifndef JSLEX_H_
#define JSLEX_H_
#include "jsutils.h"
#include "jsvar.h"
typedef struct JsLex
{
// Actual Lexing related stuff
char currCh, nextCh;
short tk; ///< The type of the token that we have
JslCharPos tokenStart; ///< Position in the data at the beginning of the token we have here
JslCharPos tokenEnd; ///< Position in the data at the last character of the token we have here
JslCharPos tokenLastStart; ///< Position in the data of the first character of the last token
JslCharPos tokenLastEnd; ///< Position in the data of the last character of the last token
char token[JSLEX_MAX_TOKEN_LENGTH]; ///< Data contained in the token we have here
JsVar *tokenValue; ///< JsVar containing the current token - used only for strings
unsigned char tokenl; ///< the current length of token
/* Where we get our data from...
*
* This is a bit more tricky than normal because the data comes from JsVars,
* which only have fixed length strings. If we go past this, we have to go
* to the next jsVar...
*/
JsVar *sourceVar; // the actual string var
JsvStringIterator it; // Iterator for the string
} JsLex;
void jslInit(JsLex *lex, JsVar *var);
void jslKill(JsLex *lex);
void jslReset(JsLex *lex);
void jslSeekTo(JsLex *lex, JslCharPos seekToChar); // like jslSeek, but pre-fills characters
bool jslMatch(JsLex *lex, int expected_tk); ///< Match, and return true on success, false on failure
void jslTokenAsString(int token, char *str, size_t len); ///< output the given token as a string - for debugging
void jslGetTokenString(JsLex *lex, char *str, size_t len);
char *jslGetTokenValueAsString(JsLex *lex);
JsVar *jslGetTokenValueAsVar(JsLex *lex);
// Only for more 'internal' use
void jslSeek(JsLex *lex, JslCharPos seekToChar); // like jslSeekTo, but doesn't pre-fill characters
void jslGetNextCh(JsLex *lex);
void jslGetNextToken(JsLex *lex); ///< Get the text token from our text string
#endif /* JSLEX_H_ */

2213
components/external/espruino/src/jsparse.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,126 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* Recursive descent parser for code execution
* ----------------------------------------------------------------------------
*/
#ifndef JSPARSE_H_
#define JSPARSE_H_
#include "jsvar.h"
#include "jslex.h"
typedef struct {
JsVar *root; ///< root of symbol table
} JsParse;
void jspInit(JsParse *parse);
void jspKill(JsParse *parse);
// jspSoft* - 'release' or 'claim' anything we are using, but ensure that it doesn't get freed
void jspSoftInit(JsParse *parse); ///< used when recovering from or saving to flash
void jspSoftKill(JsParse *parse); ///< used when recovering from or saving to flash
bool jspIsCreatedObject(JsParse *parse, JsVar *v); ///< Is v likely to have been created by this parser?
/** Returns true if the constructor function given is the same as that
* of the object with the given name. */
bool jspIsConstructor(JsVar *constructor, const char *constructorName);
/// Create a new built-in object that jswrapper can use to check for built-in functions
JsVar *jspNewBuiltin(const char *name);
/** Create a new object of the given instance and add it to root with name 'name'.
* If name!=0, added to root with name, and the name is returned
* If name==0, not added to root and Object itself returned */
JsVar *jspNewObject(JsParse *parse, const char *name, const char *instanceOf);
/// if interrupting execution, this is set
bool jspIsInterrupted();
/// if interrupting execution, this is set
void jspSetInterrupted(bool interrupt);
/// Has there been an error during parsing
bool jspHasError();
bool jspAddNativeFunction(JsParse *parse, const char *funcDesc, JsCallback callbackPtr);
JsVar *jspEvaluateVar(JsParse *parse, JsVar *str, JsVar *scope);
JsVar *jspEvaluate(JsParse *parse, const char *str);
bool jspExecuteFunction(JsParse *parse, JsVar *func, JsVar *parent, int argCount, JsVar **argPtr);
/// Evaluate a JavaScript module and return its exports
JsVar *jspEvaluateModule(JsParse *parse, JsVar *moduleContents);
/** When parsing, this enum defines whether
we are executing or not */
typedef enum {
EXEC_NO = 0,
EXEC_YES = 1,
EXEC_BREAK = 2,
EXEC_CONTINUE = 4,
EXEC_INTERRUPTED = 8, // true if execution has been interrupted
EXEC_ERROR = 16,
EXEC_ERROR_LINE_REPORTED = 32, // if an error has been reported, set this so we don't do it too much
EXEC_FOR_INIT = 64, // when in for initialiser parsing - hack to avoid getting confused about multiple use for IN
EXEC_IN_LOOP = 128, // when in a loop, set this - we can then block break/continue outside it
EXEC_IN_SWITCH = 256, // when in a switch, set this - we can then block break outside it/loops
EXEC_RUN_MASK = EXEC_YES|EXEC_BREAK|EXEC_CONTINUE|EXEC_INTERRUPTED,
EXEC_ERROR_MASK = EXEC_INTERRUPTED|EXEC_ERROR,
EXEC_SAVE_RESTORE_MASK = EXEC_YES|EXEC_IN_LOOP|EXEC_IN_SWITCH, // the things JSP_SAVE/RESTORE_EXECUTE should keep track of
} JsExecFlags;
/** This structure is used when parsing the JavaScript. It contains
* everything that should be needed. */
typedef struct {
JsParse *parse;
JsLex *lex;
// TODO: could store scopes as JsVar array for speed
JsVarRef scopes[JSPARSE_MAX_SCOPES];
int scopeCount;
/// Value of 'this' reserved word
JsVar *thisVar;
JsExecFlags execute;
} JsExecInfo;
/// flags for jspParseFunction
typedef enum {
JSP_NOSKIP_A = 1,
JSP_NOSKIP_B = 2,
JSP_NOSKIP_C = 4,
JSP_NOSKIP_D = 8,
JSP_NOSKIP_E = 16,
JSP_NOSKIP_F = 32,
JSP_NOSKIP_G = 64,
JSP_NOSKIP_H = 128,
} JspSkipFlags;
/// parse function with max 4 arguments (can set arg to 0 to avoid parse). Usually first arg will be 0, but if we DON'T want to skip names on an arg stuff, we can say
bool jspParseFunction(JspSkipFlags skipName, JsVar **a, JsVar **b, JsVar **c, JsVar **d);
/// parse function with max 8 arguments (can set arg to 0 to avoid parse). Usually first arg will be 0, but if we DON'T want to skip names on an arg stuff, we can say
bool jspParseFunction8(JspSkipFlags skipName, JsVar **a, JsVar **b, JsVar **c, JsVar **d, JsVar **e, JsVar **f, JsVar **g, JsVar **h);
bool jspParseVariableName(); ///< parse single variable name
bool jspParseEmptyFunction(); ///< parse function with no arguments
JsVar *jspParseSingleFunction(); ///< parse function with a single argument, return its value (no names!)
JsVar *jspParseFunctionAsArray(); ///< parse a function with any number of argument, and return an array of de-named aruments
/** Handle a function call (assumes we've parsed the function name and we're
* on the start bracket). 'thisArg' is the value of the 'this' variable when the
* function is executed (it's usually the parent object)
*
* If !isParsing and arg0!=0, argument 0 is set to what is supplied (same with arg1)
*
* functionName is used only for error reporting - and can be 0
*/
JsVar *jspeFunctionCall(JsVar *function, JsVar *functionName, JsVar *thisArg, bool isParsing, int argCount, JsVar **argPtr);
#endif /* JSPARSE_H_ */

150
components/external/espruino/src/jspin.c vendored Normal file
View File

@@ -0,0 +1,150 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* Utilities and definitions for handling Pins
* ----------------------------------------------------------------------------
*/
#include "jspin.h"
#include "jspininfo.h" // auto-generated
bool jshIsPinValid(Pin pin) {
// Note, PIN_UNDEFINED is always > JSH_PIN_COUNT
return pin < JSH_PIN_COUNT && pinInfo[pin].port!=JSH_PORT_NONE;
}
Pin jshGetPinFromString(const char *s) {
// built in constants
if (s[0]=='B' && s[1]=='T' && s[2]=='N') {
#ifdef BTN1_PININDEX
if (!s[3]) return BTN1_PININDEX;
if (s[3]=='1' && !s[4]) return BTN1_PININDEX;
#endif
#ifdef BTN2_PININDEX
if (s[3]=='2' && !s[4]) return BTN2_PININDEX;
#endif
#ifdef BTN3_PININDEX
if (s[3]=='3' && !s[4]) return BTN3_PININDEX;
#endif
#ifdef BTN4_PININDEX
if (s[3]=='4' && !s[4]) return BTN4_PININDEX;
#endif
}
if (s[0]=='L' && s[1]=='E' && s[2]=='D') {
#ifdef LED1_PININDEX
if (!s[3]) return LED1_PININDEX;
if (s[3]=='1' && !s[4]) return LED1_PININDEX;
#endif
#ifdef LED2_PININDEX
if (s[3]=='2' && !s[4]) return LED2_PININDEX;
#endif
#ifdef LED3_PININDEX
if (s[3]=='3' && !s[4]) return LED3_PININDEX;
#endif
#ifdef LED4_PININDEX
if (s[3]=='4' && !s[4]) return LED4_PININDEX;
#endif
#ifdef LED5_PININDEX
if (s[3]=='5' && !s[4]) return LED5_PININDEX;
#endif
#ifdef LED6_PININDEX
if (s[3]=='6' && !s[4]) return LED6_PININDEX;
#endif
#ifdef LED7_PININDEX
if (s[3]=='7' && !s[4]) return LED7_PININDEX;
#endif
#ifdef LED8_PININDEX
if (s[3]=='8' && !s[4]) return LED8_PININDEX;
#endif
}
if ((s[0]>='A' && s[0]<='H') && s[1]) { // first 6 are analogs
int port = JSH_PORTA+s[0]-'A';
Pin pin = 127;
if (!s[2] && (s[1]>='0' && s[1]<='9')) { // D0-D9
pin = (Pin)(s[1]-'0');
} else if (!s[3] && (s[1]>='1' && s[1]<='3' && s[2]>='0' && s[2]<='9')) { // D1X-D3X
pin = (Pin)((s[1]-'0')*10 + (s[2]-'0'));
}
if (port == JSH_PORTA) {
if (pin<JSH_PORTA_COUNT) return (Pin)(JSH_PORTA_OFFSET + pin);
} else if (port == JSH_PORTB) {
if (pin<JSH_PORTB_COUNT) return (Pin)(JSH_PORTB_OFFSET + pin);
} else if (port == JSH_PORTC) {
if (pin<JSH_PORTC_COUNT) return (Pin)(JSH_PORTC_OFFSET + pin);
} else if (port == JSH_PORTD) {
if (pin<JSH_PORTD_COUNT) return (Pin)(JSH_PORTD_OFFSET + pin);
#if JSH_PORTE_OFFSET!=-1
} else if (port == JSH_PORTE) {
if (pin<JSH_PORTE_COUNT) return (Pin)(JSH_PORTE_OFFSET + pin);
#endif
#if JSH_PORTF_OFFSET!=-1
} else if (port == JSH_PORTF) {
if (pin<JSH_PORTF_COUNT) return (Pin)(JSH_PORTF_OFFSET + pin);
#endif
#if JSH_PORTG_OFFSET!=-1
} else if (port == JSH_PORTG) {
if (pin<JSH_PORTG_COUNT) return (Pin)(JSH_PORTG_OFFSET + pin);
#endif
#if JSH_PORTH_OFFSET!=-1
} else if (port == JSH_PORTH) {
if (pin<JSH_PORTH_COUNT) return (Pin)(JSH_PORTH_OFFSET + pin);
#endif
}
}
return PIN_UNDEFINED;
}
/** Write the pin name to a string. String must have at least 8 characters (to be safe) */
void jshGetPinString(char *result, Pin pin) {
result[0] = 0; // just in case
if (
#if JSH_PORTA_OFFSET!=0
pin>=JSH_PORTA_OFFSET &&
#endif
pin<JSH_PORTA_OFFSET+JSH_PORTA_COUNT) {
result[0]='A';
itoa(pin-JSH_PORTA_OFFSET,&result[1],10);
} else if (pin>=JSH_PORTB_OFFSET && pin<JSH_PORTB_OFFSET+JSH_PORTB_COUNT) {
result[0]='B';
itoa(pin-JSH_PORTB_OFFSET,&result[1],10);
} else if (pin>=JSH_PORTC_OFFSET && pin<JSH_PORTC_OFFSET+JSH_PORTC_COUNT) {
result[0]='C';
itoa(pin-JSH_PORTC_OFFSET,&result[1],10);
} else if (pin>=JSH_PORTD_OFFSET && pin<JSH_PORTD_OFFSET+JSH_PORTD_COUNT) {
result[0]='D';
itoa(pin-JSH_PORTD_OFFSET,&result[1],10);
#if JSH_PORTE_OFFSET!=-1
} else if (pin>=JSH_PORTE_OFFSET && pin<JSH_PORTE_OFFSET+JSH_PORTE_COUNT) {
result[0]='E';
itoa(pin-JSH_PORTE_OFFSET,&result[1],10);
#endif
#if JSH_PORTF_OFFSET!=-1
} else if (pin>=JSH_PORTF_OFFSET && pin<JSH_PORTF_OFFSET+JSH_PORTF_COUNT) {
result[0]='F';
itoa(pin-JSH_PORTF_OFFSET,&result[1],10);
#endif
#if JSH_PORTG_OFFSET!=-1
} else if (pin>=JSH_PORTG_OFFSET && pin<JSH_PORTG_OFFSET+JSH_PORTG_COUNT) {
result[0]='G';
itoa(pin-JSH_PORTG_OFFSET,&result[1],10);
#endif
#if JSH_PORTH_OFFSET!=-1
} else if (pin>=JSH_PORTH_OFFSET && pin<JSH_PORTH_OFFSET+JSH_PORTH_COUNT) {
result[0]='H';
itoa(pin-JSH_PORTH_OFFSET,&result[1],10);
#endif
} else {
strncpy(result, "UNKNOWN", 8);
}
}

228
components/external/espruino/src/jspin.h vendored Normal file
View File

@@ -0,0 +1,228 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* Utilities and definitions for handling Pins
* ----------------------------------------------------------------------------
*/
#ifndef JSPIN_H
#define JSPIN_H
#include "jsutils.h"
#include "jsvar.h"
typedef unsigned char Pin; ///< for specifying pins for hardware
#define PIN_UNDEFINED ((Pin)0xFF)
typedef enum {
JSH_PORT_NONE,
JSH_PORTA=1,
JSH_PORTB,
JSH_PORTC,
JSH_PORTD,
JSH_PORTE,
JSH_PORTF,
JSH_PORTG,
JSH_PORTH,
} PACKED_FLAGS JsvPinInfoPort;
typedef enum {
JSH_PIN0 = 0,
JSH_PIN1,
JSH_PIN2,
JSH_PIN3,
JSH_PIN4,
JSH_PIN5,
JSH_PIN6,
JSH_PIN7,
JSH_PIN8,
JSH_PIN9,
JSH_PIN10,
JSH_PIN11,
JSH_PIN12,
JSH_PIN13,
JSH_PIN14,
JSH_PIN15,
#ifndef ARM
JSH_PIN16,
JSH_PIN17,
JSH_PIN18,
JSH_PIN19,
JSH_PIN20,
JSH_PIN21,
JSH_PIN22,
JSH_PIN23,
JSH_PIN24,
JSH_PIN25,
JSH_PIN26,
JSH_PIN27,
JSH_PIN28,
JSH_PIN29,
JSH_PIN30,
JSH_PIN31,
#endif
} PACKED_FLAGS JsvPinInfoPin;
typedef enum {
JSH_ANALOG_NONE = 0,
JSH_ANALOG1 = 32,
JSH_ANALOG2 = 64,
JSH_ANALOG3 = 128,
JSH_ANALOG4 = 256,
JSH_ANALOG12 = JSH_ANALOG1|JSH_ANALOG2,
JSH_ANALOG123 = JSH_ANALOG1|JSH_ANALOG2|JSH_ANALOG3,
JSH_ANALOG34 = JSH_ANALOG3|JSH_ANALOG4,
JSH_ANALOG_CH0 = 0,
JSH_ANALOG_CH1,
JSH_ANALOG_CH2,
JSH_ANALOG_CH3,
JSH_ANALOG_CH4,
JSH_ANALOG_CH5,
JSH_ANALOG_CH6,
JSH_ANALOG_CH7,
JSH_ANALOG_CH8,
JSH_ANALOG_CH9,
JSH_ANALOG_CH10,
JSH_ANALOG_CH11,
JSH_ANALOG_CH12,
JSH_ANALOG_CH13,
JSH_ANALOG_CH14,
JSH_ANALOG_CH15,
JSH_ANALOG_CH16,
JSH_MASK_ANALOG_CH = 31,
JSH_MASK_ANALOG_ADC = JSH_ANALOG1|JSH_ANALOG2|JSH_ANALOG3|JSH_ANALOG4,
} PACKED_FLAGS JsvPinInfoAnalog;
typedef enum {
// ---------------------------- JSH_MASK_AF
JSH_AF0 = 0,
JSH_AF1,
JSH_AF2,
JSH_AF3,
JSH_AF4,
JSH_AF5,
JSH_AF6,
JSH_AF7,
JSH_AF8,
JSH_AF9,
JSH_AF10,
JSH_AF11,
JSH_AF12,
JSH_AF13,
JSH_AF14,
JSH_AF15,
// ---------------------------- JSH_MASK_TYPE
JSH_TIMER1 = 0x0010,
JSH_TIMER2 = 0x0020,
JSH_TIMER3 = 0x0030,
JSH_TIMER4 = 0x0040,
JSH_TIMER5 = 0x0050,
JSH_TIMER6 = 0x0060,
JSH_TIMER7 = 0x0070,
JSH_TIMER8 = 0x0080,
JSH_TIMER9 = 0x0090,
JSH_TIMER10 = 0x00A0,
JSH_TIMER11 = 0x00B0,
JSH_TIMER12 = 0x00C0,
JSH_TIMER13 = 0x00D0,
JSH_TIMER14 = 0x00E0,
JSH_TIMER15 = 0x00F0,
JSH_TIMER16 = 0x0100,
JSH_TIMER17 = 0x0110,
JSH_TIMER18 = 0x0120,
JSH_TIMERMAX = JSH_TIMER18,
JSH_DAC = 0x0180,
JSH_SPI1 = 0x0200,
JSH_SPI2 = 0x0210,
JSH_SPI3 = 0x0220,
JSH_SPIMAX = JSH_SPI3,
JSH_I2C1 = 0x0280,
JSH_I2C2 = 0x0290,
JSH_I2C3 = 0x02A0,
JSH_I2CMAX = JSH_I2C3,
JSH_USART1 = 0x0300,
JSH_USART2 = 0x0310,
JSH_USART3 = 0x0320,
JSH_USART4 = 0x0330,
JSH_USART5 = 0x0340,
JSH_USART6 = 0x0350,
JSH_USARTMAX = JSH_USART6,
// ---------------------------- JSH_MASK_INFO
JSH_TIMER_CH1 = 0x0000,
JSH_TIMER_CH2 = 0x1000,
JSH_TIMER_CH3 = 0x2000,
JSH_TIMER_CH4 = 0x3000,
JSH_MASK_TIMER_CH = 0x7000,
JSH_TIMER_NEGATED = 0x8000,
JSH_USART_RX = 0x0000,
JSH_USART_TX = 0x1000,
JSH_SPI_MISO = 0x0000,
JSH_SPI_MOSI = 0x1000,
JSH_SPI_SCK = 0x2000,
JSH_I2C_SCL = 0x0000,
JSH_I2C_SDA = 0x1000,
JSH_DAC_CH1 = 0x0000,
JSH_DAC_CH2 = 0x1000,
// ---------------------------- Masks
JSH_MASK_AF = 0x000F,
JSH_MASK_TYPE = 0x0FF0,
JSH_MASK_INFO = 0xF000,
} PACKED_FLAGS JshPinFunction;
#define JSH_PINFUNCTION_IS_TIMER(F) ( \
(((F)&JSH_MASK_TYPE)>=JSH_TIMER1) && \
(((F)&JSH_MASK_TYPE)<=JSH_TIMER18))
#define JSH_PINFUNCTION_IS_DAC(F) ( \
(((F)&JSH_MASK_TYPE)==JSH_DAC) || \
0 )
#define JSH_PINFUNCTION_IS_USART(F) ( \
(((F)&JSH_MASK_TYPE)>=JSH_USART1) && \
(((F)&JSH_MASK_TYPE)<=JSH_USART6))
#define JSH_PINFUNCTION_IS_I2C(F) ( \
(((F)&JSH_MASK_TYPE)>=JSH_I2C1) && \
(((F)&JSH_MASK_TYPE)<=JSH_I2CMAX))
#define JSH_PINFUNCTION_IS_SPI(F) ( \
(((F)&JSH_MASK_TYPE)>=JSH_SPI1) && \
(((F)&JSH_MASK_TYPE)<=JSH_SPIMAX))
bool jshIsPinValid(Pin pin); ///< is the specific pin actually valid?
/// Given a string, convert it to a pin ID (or -1 if it doesn't exist)
Pin jshGetPinFromString(const char *s);
/** Write the pin name to a string. String must have at least 8 characters (to be safe) */
void jshGetPinString(char *result, Pin pin);
/// Given a var, convert it to a pin ID (or -1 if it doesn't exist). safe for undefined!
static inline Pin jshGetPinFromVar(JsVar *pinv) {
if (jsvIsString(pinv) && pinv->varData.str[5]==0/*should never be more than 4 chars!*/) {
return jshGetPinFromString(&pinv->varData.str[0]);
} else if (jsvIsInt(pinv) /* This also tests for the Pin datatype */) {
return (Pin)jsvGetInteger(pinv);
} else return PIN_UNDEFINED;
}
static inline Pin jshGetPinFromVarAndUnLock(JsVar *pinv) {
Pin pin = jshGetPinFromVar(pinv);
jsvUnLock(pinv);
return pin;
}
#endif //JSPIN_H

View File

@@ -0,0 +1,439 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* Misc utils and cheapskate stdlib implementation
* ----------------------------------------------------------------------------
*/
#include "jsutils.h"
#include "jslex.h"
#include "jshardware.h"
#include "jsinteractive.h"
// needed for isnan / isfinite
#ifdef ARM
#include "mconf.h"
#include "protos.h"
#else
#include <math.h>
#endif
extern double jswrap_math_pow(double x, double y); // for pow
bool isIDString(const char *s) {
if (!isAlpha(*s))
return false;
while (*s) {
if (!(isAlpha(*s) || isNumeric(*s)))
return false;
s++;
}
return true;
}
/** escape a character - if it is required. This may return a reference to a static array,
so you can't store the value it returns in a variable and call it again. */
const char *escapeCharacter(char ch) {
if (ch=='\b') return "\\b";
if (ch=='\f') return "\\f";
if (ch=='\n') return "\\n";
if (ch=='\a') return "\\a";
if (ch=='\r') return "\\r";
if (ch=='\t') return "\\t";
if (ch=='\\') return "\\\\";
if (ch=='"') return "\\\"";
static char buf[5];
if (ch<32) {
/** just encode as hex - it's more understandable
* and doesn't have the issue of "\16"+"1" != "\161" */
buf[0]='\\';
buf[1]='x';
int n = (ch>>4)&15;
buf[2] = (char)((n<10)?('0'+n):('A'+n-10));
n=ch&15;
buf[3] = (char)((n<10)?('0'+n):('A'+n-10));
buf[4] = 0;
return buf;
}
buf[1] = 0;
buf[0] = ch;
return buf;
}
/* convert a number in the given radix to an int. if radix=0, autodetect */
JsVarInt stringToIntWithRadix(const char *s, int forceRadix, bool *hasError) {
bool isNegated = false;
JsVarInt v = 0;
JsVarInt radix = 10;
if (*s == '-') {
isNegated = true;
s++;
}
if (*s == '0') {
radix = 8;
s++;
// OctalIntegerLiteral: 0o01, 0O01
if (*s == 'o' || *s == 'O') {
radix = 8;
s++;
// HexIntegerLiteral: 0x01, 0X01
} else if (*s == 'x' || *s == 'X') {
radix = 16;
s++;
// BinaryIntegerLiteral: 0b01, 0B01
} else if (*s == 'b' || *s == 'B') {
radix = 2;
s++;
}
}
if (forceRadix>0 && forceRadix<=36)
radix = forceRadix;
while (*s) {
int digit = 0;
if (*s >= '0' && *s <= '9')
digit = (*s - '0');
else if (*s >= 'a' && *s <= 'f')
digit = (10 + *s - 'a');
else if (*s >= 'A' && *s <= 'F')
digit = (10 + *s - 'A');
else break;
if (digit>=radix)
break;
v = v*radix + digit;
s++;
}
if (hasError) *hasError = *s!=0; // we're ok if we reached the end of the string
if (isNegated) return -v;
return v;
}
/* convert hex, binary, octal or decimal string into an int */
JsVarInt stringToInt(const char *s) {
return stringToIntWithRadix(s,0,0);
}
void jsError(const char *fmt, ...) {
jsiConsoleRemoveInputLine();
jsiConsolePrint("ERROR: ");
va_list argp;
va_start(argp, fmt);
vcbprintf((vcbprintf_callback)jsiConsolePrint,0, fmt, argp);
va_end(argp);
jsiConsolePrint("\n");
}
void jsErrorInternal(const char *fmt, ...) {
jsiConsoleRemoveInputLine();
jsiConsolePrint("INTERNAL ERROR: ");
va_list argp;
va_start(argp, fmt);
vcbprintf((vcbprintf_callback)jsiConsolePrint,0, fmt, argp);
va_end(argp);
jsiConsolePrint("\n");
}
void jsErrorAt(const char *message, struct JsLex *lex, int tokenPos) {
jsiConsoleRemoveInputLine();
jsiConsolePrint("ERROR: ");
jsiConsolePrint(message);
jsiConsolePrint(" at ");
jsiConsolePrintPosition(lex, tokenPos);
jsiConsolePrintTokenLineMarker(lex, tokenPos);
}
void jsWarn(const char *fmt, ...) {
jsiConsoleRemoveInputLine();
jsiConsolePrint("WARNING: ");
va_list argp;
va_start(argp, fmt);
vcbprintf((vcbprintf_callback)jsiConsolePrint,0, fmt, argp);
va_end(argp);
jsiConsolePrint("\n");
}
void jsWarnAt(const char *message, struct JsLex *lex, int tokenPos) {
jsiConsoleRemoveInputLine();
jsiConsolePrint("WARNING: ");
jsiConsolePrint(message);
jsiConsolePrint(" at ");
jsiConsolePrintPosition(lex, tokenPos);
}
void jsAssertFail(const char *file, int line, const char *expr) {
jsiConsoleRemoveInputLine();
if (expr) {
jsiConsolePrintf("ASSERT(%s) FAILED AT ", expr);
} else
jsiConsolePrint("ASSERT FAILED AT ");
jsiConsolePrintf("%s:%d\n",file,line);
jsvTrace(jsvGetRef(jsvFindOrCreateRoot()), 2);
exit(1);
}
#ifdef SDCC
void exit(int errcode) {dst;
jsiConsolePrint("EXIT CALLED.\n");
}
#endif
#ifdef FAKE_STDLIB
int __errno;
void exit(int errcode) {
NOT_USED(errcode);
jsiConsolePrint("EXIT CALLED.\n");
while (1);
}
char * strncat(char *dst, const char *src, size_t c) {
char *dstx = dst;
while (*(++dstx)) c--;
while (*src && c>1) {
*(dstx++) = *(src++);
c--;
}
if (c>0) *dstx = 0;
return dst;
}
char *strncpy(char *dst, const char *src, size_t c) {
char *dstx = dst;
while (*src && c>1) {
*(dstx++) = *(src++);
c--;
}
if (c>0) *dstx = 0;
return dst;
}
size_t strlen(const char *s) {
size_t l=0;
while (*(s++)) l++;
return l;
}
int strcmp(const char *a, const char *b) {
while (*a && *b) {
if (*a != *b)
return *a - *b; // correct?
a++;b++;
}
return *a - *b;
}
void *memcpy(void *dst, const void *src, size_t size) {
size_t i;
for (i=0;i<size;i++)
((char*)dst)[i] = ((char*)src)[i];
return dst;
}
void *memset(void *dst, int val, size_t size) {
unsigned char *d = (unsigned char*)dst;
unsigned int i;
for (i=0;i<size;i++)
d[i]=(unsigned char)val;
return dst;
}
unsigned int rand() {
static unsigned int m_w = 0xDEADBEEF; /* must not be zero */
static unsigned int m_z = 0xCAFEBABE; /* must not be zero */
m_z = 36969 * (m_z & 65535) + (m_z >> 16);
m_w = 18000 * (m_w & 65535) + (m_w >> 16);
return (m_z << 16) + m_w; /* 32-bit result */
}
#endif
JsVarFloat stringToFloat(const char *s) {
bool isNegated = false;
JsVarFloat v = 0;
JsVarFloat mul = 0.1;
if (*s == '-') {
isNegated = true;
s++;
}
// handle integer part
while (*s) {
if (*s >= '0' && *s <= '9')
v = (v*10) + (*s - '0');
else break;
s++;
}
// handle decimal point
if (*s == '.') {
s++; // skip .
while (*s) {
if (*s >= '0' && *s <= '9')
v += mul*(*s - '0');
else break;
mul /= 10;
s++;
}
}
// handle exponentials
if (*s == 'e' || *s == 'E') {
s++; // skip E
bool isENegated = false;
if (*s == '-' || *s == '+') {
isENegated = *s=='-';
s++;
}
int e = 0;
while (*s) {
if (*s >= '0' && *s <= '9')
e = (e*10) + (*s - '0');
else break;
s++;
}
if (isENegated) e=-e;
v = v * jswrap_math_pow(10, e);
}
// check we have parsed everything
if (*s!=0) return NAN;
if (isNegated) return -v;
return v;
}
char itoch(int val) {
if (val<10) return (char)('0'+val);
return (char)('A'+val-10);
}
#ifndef HAS_STDLIB
void itoa(JsVarInt vals,char *str,unsigned int base) {
JsVarIntUnsigned val;
if (vals<0) {
*(str++)='-';
val = (JsVarIntUnsigned)(-vals);
} else {
val = (JsVarIntUnsigned)vals;
}
JsVarIntUnsigned d = 1;
while (d*base <= val) d*=base;
while (d > 1) {
unsigned int v = (unsigned int)(val / d);
val -= v*d;
*(str++) = itoch((int)v);
d /= base;
}
*(str++)=itoch((int)val);
*(str++)=0;
}
#endif
void ftoa(JsVarFloat val,char *str) {
if (isnan(val)) strncpy(str,"NaN",4);
else if (!isfinite(val)) {
if (val<0) strncpy(str,"-Infinity",10);
else strncpy(str,"Infinity",10);
} else {
const JsVarFloat base = 10;
if (val<0) {
*(str++)='-';
val = -val;
}
JsVarFloat d = 1;
while (d*base <= val) d*=base;
while (d >= 1) {
int v = (int)(val / d);
val -= v*d;
*(str++)=itoch(v);
d /= base;
}
#ifndef USE_NO_FLOATS
if (val>0) {
*(str++)='.';
while (val>0.000001) {
int v = (int)((val / d) + 0.0000005);
val -= v*d;
*(str++)=itoch(v);
d /= base;
}
}
#endif
*(str++)=0;
}
}
/// Wrap a value so it is always between 0 and size (eg. wrapAround(angle, 360))
JsVarFloat wrapAround(JsVarFloat val, JsVarFloat size) {
val = val / size;
val = val - (int)val;
return val * size;
}
/** Espruino-special printf with a callback
* Supported are:
* %d = int
* %x = int as hex
* %L = JsVarInt
* %Lx = JsVarInt as hex
* %f = JsVarFloat
* %s = string (char *)
* %c = char
* %v = JsVar * (prints var as string)
* %t = JsVar * (prints type of var)
* %p = Pin
*
* Anything else will assert
*/
void vcbprintf(vcbprintf_callback user_callback, void *user_data, const char *fmt, va_list argp) {
char buf[32];
while (*fmt) {
if (*fmt == '%') {
fmt++;
switch (*fmt++) {
case 'd': itoa(va_arg(argp, int), buf, 10); user_callback(buf,user_data); break;
case 'x': itoa(va_arg(argp, int), buf, 16); user_callback(buf,user_data); break;
case 'L': {
unsigned int rad = 10;
if (*fmt=='x') { rad=16; fmt++; }
itoa(va_arg(argp, JsVarInt), buf, rad); user_callback(buf,user_data);
} break;
case 'f': ftoa(va_arg(argp, JsVarFloat), buf); user_callback(buf,user_data); break;
case 's': user_callback(va_arg(argp, char *), user_data); break;
case 'c': buf[0]=(char)va_arg(argp, int/*char*/);buf[1]=0; user_callback(buf, user_data); break;
case 'v': {
JsVar *v = jsvAsString(va_arg(argp, JsVar*), false/*no unlock*/);
buf[1] = 0;
JsvStringIterator it;
jsvStringIteratorNew(&it, v, 0);
// OPT: this could be faster than it is (sending whole blocks at once)
while (jsvStringIteratorHasChar(&it)) {
buf[0] = jsvStringIteratorGetChar(&it);
user_callback(buf,user_data);
jsvStringIteratorNext(&it);
}
jsvStringIteratorFree(&it);
jsvUnLock(v);
} break;
case 't': user_callback(jsvGetTypeOf(va_arg(argp, JsVar*)), user_data); break;
case 'p': jshGetPinString(buf, (Pin)va_arg(argp, int/*Pin*/)); user_callback(buf, user_data); break;
default: assert(0); return; // eep
}
} else {
buf[0] = *(fmt++);
buf[1] = 0;
user_callback(&buf[0], user_data);
}
}
}

View File

@@ -0,0 +1,374 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* Misc utils and cheapskate stdlib implementation
* ----------------------------------------------------------------------------
*/
#ifndef JSUTILS_H_
#define JSUTILS_H_
#include "platform_config.h"
#ifndef FAKE_STDLIB
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#endif
#include <stdarg.h> // for va_args
#define JS_VERSION "1v46"
/*
In code:
TODO - should be fixed
FIXME - will probably break if used
OPT - potential for speed optimisation
*/
// surely bool is defined??
#ifdef RT_USING_JS
typedef unsigned int size_t;
#else
#ifdef ARM
typedef unsigned int size_t;
#define alloca(x) __builtin_alloca(x)
#endif
#endif
#if !defined(__USB_TYPE_H) && !defined(CPLUSPLUS) // it is defined in this file too!
typedef enum {FALSE = 0, TRUE = !FALSE} bool;
//typedef unsigned char bool;
//#define TRUE (1)
//#define FALSE (0)
#endif
#define true (1)
#define false (0)
#define NAN (((JsVarFloat)0)/(JsVarFloat)0)
/* Number of Js Variables allowed and Js Reference format.
JsVarRef = char -> 15 bytes/JsVar so JSVAR_CACHE_SIZE = (RAM - 3000) / 15
JsVarRef = short -> 20 bytes/JsVar so JSVAR_CACHE_SIZE = (RAM - 3000) / 20
JsVarRef = int -> 26 bytes/JsVar so JSVAR_CACHE_SIZE = (RAM - 3000) / 26
NOTE: JSVAR_CACHE_SIZE must be at least 2 less than the number we can fit in JsVarRef
See jshardware.c FLASH constants - all this must be able to fit in flash
*/
#ifdef RESIZABLE_JSVARS
// probably linux - allow us to allocate more blocks of variables
typedef unsigned int JsVarRef;
#define JSVAR_SIZE 30
#define JSVAR_DATA_STRING_LEN 8 // Actually 9 seems like a good number as 'prototype'==9
#define JSVAR_DATA_STRING_MAX_LEN 24 // (JSVAR_DATA_STRING_LEN + sizeof(JsVarRef)*3 + sizeof(JsVarRefCounter)) - but see JSV_STRING_LEN_MAX - WE HAVE TO CLIP!
#else
/** JsVerRef stores References for variables - We treat 0 as null
* NOTE: we store JSVAR_DATA_STRING_* as actual values so we can do #if on them below
*
*/
#if JSVAR_CACHE_SIZE <= 254
typedef unsigned char JsVarRef;
#define JSVAR_SIZE 15
#define JSVAR_DATA_STRING_LEN 8 // Actually 9 seems like a good number as 'prototype'==9
#define JSVAR_DATA_STRING_MAX_LEN 12 // (JSVAR_DATA_STRING_LEN + sizeof(JsVarRef)*3 + sizeof(JsVarRefCounter)) - but see JSV_STRING_LEN_MAX too
#else
typedef unsigned short JsVarRef;
#define JSVAR_SIZE 20
#define JSVAR_DATA_STRING_LEN 8 // Actually 9 seems like a good number as 'prototype'==9
#define JSVAR_DATA_STRING_MAX_LEN 16 // (JSVAR_DATA_STRING_LEN + sizeof(JsVarRef)*3 + sizeof(JsVarRefCounter)) - but see JSV_STRING_LEN_MAX too - WE HAVE TO CLIP!
#endif
#endif
typedef long long JsVarInt;
typedef unsigned long long JsVarIntUnsigned;
#ifdef USE_FLOATS
typedef float JsVarFloat;
#else
typedef double JsVarFloat;
#endif
typedef short JslCharPos;
#define JSSYSTIME_MAX 0x7FFFFFFFFFFFFFFFLL
typedef long long JsSysTime;
#define JSLEX_MAX_TOKEN_LENGTH 64
#define JS_ERROR_BUF_SIZE 64 // size of buffer error messages are written into
#define JS_ERROR_TOKEN_BUF_SIZE 16 // see jslTokenAsString
#define JS_NUMBER_BUFFER_SIZE 24
#define JSPARSE_MAX_SCOPES 8
// Don't restrict number of iterations now
//#define JSPARSE_MAX_LOOP_ITERATIONS 8192
#define STRINGIFY_HELPER(x) #x
#define STRINGIFY(x) STRINGIFY_HELPER(x)
#define NOT_USED(x) ( (void)(x) )
// javascript specific names
#define JSPARSE_RETURN_VAR "return" // variable name used for returning function results
#define JSPARSE_PROTOTYPE_VAR "prototype"
#define JSPARSE_CONSTRUCTOR_VAR "constructor"
#define JSPARSE_INHERITS_VAR "__proto__"
// internal names that hopefully nobody will be able to access
#define JS_HIDDEN_CHAR '>' // initial character of var name determines that we shouldn't see this stuff
#define JS_HIDDEN_CHAR_STR ">"
#define JSPARSE_FUNCTION_CODE_NAME JS_HIDDEN_CHAR_STR"code"
#define JSPARSE_FUNCTION_SCOPE_NAME JS_HIDDEN_CHAR_STR"scope"
#define JSPARSE_MODULE_CACHE_NAME JS_HIDDEN_CHAR_STR"modules"
#if !defined(NO_ASSERT)
#ifdef __STRING
#define assert(X) if (!(X)) jsAssertFail(__FILE__,__LINE__,__STRING(X));
#else
#define assert(X) if (!(X)) jsAssertFail(__FILE__,__LINE__,"");
#endif
#else
#define assert(X)
#endif
/// Used when we have enums we want to squash down
#define PACKED_FLAGS __attribute__ ((__packed__))
/// Used before functions that we want to ensure are not inlined (eg. "void NO_INLINE foo() {}")
#define NO_INLINE __attribute__ ((noinline))
/// Maximum amount of locks we ever expect to have on a variable (this could limit recursion) must be 2^n-1
#define JSV_LOCK_MAX 15
/// preprocessor power of 2 - suitable up to 16 bits
#define NEXT_POWER_2(X) \
(((X) | (X)>>1 | (X)>>2 | (X)>>3 | \
(X)>>4 | (X)>>5 | (X)>>6 | (X)>>7 | \
(X)>>8 | (X)>>9 | (X)>>10 | (X)>>11 | \
(X)>>12 | (X)>>13 | (X)>>14 | (X)>>15)+1)
/// Proprocessor get bit number
#define GET_BIT_NUMBER(X) \
(((X)== 1)? 0: \
((X)== 2)? 1: \
((X)== 4)? 2: \
((X)== 8)? 3: \
((X)== 16)? 4: \
((X)== 32)? 5: \
((X)== 64)? 6: \
((X)== 128)? 7: \
((X)== 256)? 8: \
((X)== 512)? 9: \
((X)== 1024)?10: \
((X)== 2048)?11: \
((X)== 4096)?12: \
((X)== 8192)?13: \
((X)==16384)?14: \
((X)==32768)?15:10000/*error*/)
/** These flags are at the top of each JsVar and provide information about what it is, as
* well as how many Locks it has. Everything is packed in as much as possible to allow us to
* get down to within 2 bytes. */
typedef enum {
JSV_UNUSED = 0, ///< Variable not used for anything
JSV_ROOT = JSV_UNUSED+1, ///< The root of everything - there is only one of these
// UNDEFINED is now just stored using '0' as the variable Ref
JSV_NULL = JSV_ROOT+1, ///< it seems null is its own data type
JSV_STRING = JSV_NULL+1, ///< string
JSV_STRING_0 = JSV_STRING, // string of length 0
JSV_STRING_MAX = JSV_STRING_0+JSVAR_DATA_STRING_LEN,
JSV_STRING_EXT = JSV_STRING_MAX+1, ///< extra character data for string (if it didn't fit in first JsVar). These use unused pointer fields for extra characters
JSV_STRING_EXT_0 = JSV_STRING_EXT,
JSV_STRING_EXT_MAX = JSV_STRING_EXT_0+JSVAR_DATA_STRING_MAX_LEN,
JSV_ARRAY = JSV_STRING_EXT_MAX+1, ///< A JavaScript Array Buffer - Implemented just like a String at the moment
JSV_ARRAYBUFFER = JSV_ARRAY+1,
JSV_OBJECT = JSV_ARRAYBUFFER+1,
JSV_FUNCTION = JSV_OBJECT+1,
JSV_NUMERICSTART = JSV_FUNCTION+1, ///< --------- Start of numeric variable types
JSV_INTEGER = JSV_NUMERICSTART, ///< integer number (note JSV_NUMERICMASK)
JSV_FLOAT = JSV_INTEGER+1, ///< floating point double (note JSV_NUMERICMASK)
JSV_BOOLEAN = JSV_FLOAT+1, ///< boolean (note JSV_NUMERICMASK)
JSV_PIN = JSV_BOOLEAN+1, ///< pin (note JSV_NUMERICMASK)
JSV_NUMERICEND = JSV_PIN, ///< --------- End of numeric variable types
JSV_VAR_END = JSV_NUMERICEND, ///< End of numeric variable types
JSV_VARTYPEMASK = NEXT_POWER_2(JSV_VAR_END)-1,
// names can be STRING,
JSV_NAME = JSV_VARTYPEMASK+1, ///< a NAME of a variable - this isn't a variable itself (and can be an int/string/etc.)
JSV_NATIVE = JSV_NAME<<1, ///< to specify this is a native function, root, function parameter, OR that it should not be freed
JSV_GARBAGE_COLLECT = JSV_NATIVE<<1, ///< When garbage collecting, this flag is true IF we should GC!
JSV_IS_RECURSING = JSV_GARBAGE_COLLECT<<1, ///< used to stop recursive loops in jsvTrace
JSV_LOCK_ONE = JSV_IS_RECURSING<<1,
JSV_LOCK_MASK = JSV_LOCK_MAX * JSV_LOCK_ONE,
JSV_ARRAYBUFFERNAME = JSV_NAME|JSV_ARRAYBUFFER, ///< used for indexing into an ArrayBuffer. varData is an INT in this case
JSV_FUNCTION_PARAMETER = JSV_NATIVE | JSV_NAME, ///< this is inside a function, so it should be quite obvious
} PACKED_FLAGS JsVarFlags; // aiming to get this in 2 bytes!
/// The amount of bits we must shift to get the number of locks - forced to be a constant
static const int JSV_LOCK_SHIFT = GET_BIT_NUMBER(JSV_LOCK_ONE);
typedef enum LEX_TYPES {
LEX_EOF = 0,
LEX_ID = 256,
LEX_INT,
LEX_FLOAT,
LEX_STR,
LEX_UNFINISHED_COMMENT,
LEX_EQUAL,
LEX_TYPEEQUAL,
LEX_NEQUAL,
LEX_NTYPEEQUAL,
LEX_LEQUAL,
LEX_LSHIFT,
LEX_LSHIFTEQUAL,
LEX_GEQUAL,
LEX_RSHIFT,
LEX_RSHIFTUNSIGNED,
LEX_RSHIFTEQUAL,
LEX_RSHIFTUNSIGNEDEQUAL,
LEX_PLUSEQUAL,
LEX_MINUSEQUAL,
LEX_PLUSPLUS,
LEX_MINUSMINUS,
LEX_MULEQUAL,
LEX_DIVEQUAL,
LEX_MODEQUAL,
LEX_ANDEQUAL,
LEX_ANDAND,
LEX_OREQUAL,
LEX_OROR,
LEX_XOREQUAL,
// reserved words
#define LEX_R_LIST_START LEX_R_IF
LEX_R_IF,
LEX_R_ELSE,
LEX_R_DO,
LEX_R_WHILE,
LEX_R_FOR,
LEX_R_BREAK,
LEX_R_CONTINUE,
LEX_R_FUNCTION,
LEX_R_RETURN,
LEX_R_VAR,
LEX_R_THIS,
LEX_R_TRUE,
LEX_R_FALSE,
LEX_R_NULL,
LEX_R_UNDEFINED,
LEX_R_NEW,
LEX_R_IN,
LEX_R_INSTANCEOF,
LEX_R_SWITCH,
LEX_R_CASE,
LEX_R_DEFAULT,
LEX_R_TYPEOF,
LEX_R_VOID,
LEX_R_LIST_END /* always the last entry */
} LEX_TYPES;
// To handle variable size bit fields
#define BITFIELD_DECL(BITFIELD, N) unsigned int BITFIELD[(N+31)/32]
#define BITFIELD_GET(BITFIELD, N) ((BITFIELD[(N)>>5] >> ((N)&31))&1)
#define BITFIELD_SET(BITFIELD, N, VALUE) (BITFIELD[(N)>>5] = (BITFIELD[(N)>>5]& (unsigned int)~(1 << ((N)&31))) | (unsigned int)((VALUE)?(1 << ((N)&31)):0) )
static inline bool isWhitespace(char ch) {
return (ch==' ') || (ch=='\t') || (ch=='\n') || (ch=='\r');
}
static inline bool isNumeric(char ch) {
return (ch>='0') && (ch<='9');
}
static inline bool isHexadecimal(char ch) {
return ((ch>='0') && (ch<='9')) ||
((ch>='a') && (ch<='f')) ||
((ch>='A') && (ch<='F'));
}
static inline bool isAlpha(char ch) {
return ((ch>='a') && (ch<='z')) || ((ch>='A') && (ch<='Z')) || ch=='_';
}
bool isIDString(const char *s);
/** escape a character - if it is required. This may return a reference to a static array,
so you can't store the value it returns in a variable and call it again. */
const char *escapeCharacter(char ch);
/* convert a number in the given radix to an int. if radix=0, autodetect */
JsVarInt stringToIntWithRadix(const char *s, int radix, bool *hasError);
/* convert hex, binary, octal or decimal string into an int */
JsVarInt stringToInt(const char *s);
// forward decl
struct JsLex;
// ------------
void jsError(const char *fmt, ...);
void jsErrorInternal(const char *fmt, ...);
void jsErrorAt(const char *message, struct JsLex *lex, int tokenPos);
void jsWarn(const char *fmt, ...);
void jsWarnAt(const char *message, struct JsLex *lex, int tokenPos);
void jsAssertFail(const char *file, int line, const char *expr);
#ifdef FAKE_STDLIB
void exit(int errcode);
char *strncat(char *dst, const char *src, size_t c);
char *strncpy(char *dst, const char *src, size_t c);
size_t strlen(const char *s);
int strcmp(const char *a, const char *b);
void *memcpy(void *dst, const void *src, size_t size);
void *memset(void *dst, int val, size_t size);
#define RAND_MAX (0xFFFFFFFFU)
unsigned int rand();
#else
// FIXME: use itoa/ftoa direct - sprintf is huge
//#define itoa(val,str,base) sprintf(str,"%d",(int)val)
//#define ftoa(val,str) sprintf(str,"%f",val)
#endif
JsVarFloat stringToFloat(const char *str);
#ifndef HAS_STDLIB
void itoa(JsVarInt val,char *str,unsigned int base);
#endif
char itoch(int val);
void ftoa(JsVarFloat val,char *str);
/// Wrap a value so it is always between 0 and size (eg. wrapAround(angle, 360))
JsVarFloat wrapAround(JsVarFloat val, JsVarFloat size);
typedef void (*vcbprintf_callback)(const char *str, void *user_data);
/** Espruino-special printf with a callback
* Supported are:
* %d = int
* %x = int as hex
* %L = JsVarInt
* %Lx = JsVarInt as hex
* %f = JsVarFloat
* %s = string (char *)
* %c = char
* %v = JsVar *
* %p = Pin
*
* Anything else will assert
*/
void vcbprintf(vcbprintf_callback user_callback, void *user_data, const char *fmt, va_list argp);
#endif /* JSUTILS_H_ */

2542
components/external/espruino/src/jsvar.c vendored Normal file

File diff suppressed because it is too large Load Diff

612
components/external/espruino/src/jsvar.h vendored Normal file
View File

@@ -0,0 +1,612 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* Variables
* ----------------------------------------------------------------------------
*/
#ifndef JSVAR_H_
#define JSVAR_H_
#include "jsutils.h"
typedef void (*JsCallback)(JsVarRef var)
#ifdef SDCC
__reentrant
#endif
;
/** To avoid confusion - JsVarRefCounter should be big enough
* to store as many refs as can possibly be created - so it's
* safe just to set it to the same size as JsVarRef. However
* it is NOT a reference itself.
*/
typedef JsVarRef JsVarRefCounter;
typedef enum {
ARRAYBUFFERVIEW_UNDEFINED = 0,
ARRAYBUFFERVIEW_ARRAYBUFFER = 1 | 64, ///< Basic ArrayBuffer type
ARRAYBUFFERVIEW_MASK_SIZE = 15,
ARRAYBUFFERVIEW_SIGNED = 16,
ARRAYBUFFERVIEW_FLOAT = 32,
ARRAYBUFFERVIEW_UINT8 = 1,
ARRAYBUFFERVIEW_INT8 = 1 | ARRAYBUFFERVIEW_SIGNED,
ARRAYBUFFERVIEW_UINT16 = 2,
ARRAYBUFFERVIEW_INT16 = 2 | ARRAYBUFFERVIEW_SIGNED,
ARRAYBUFFERVIEW_UINT32 = 4,
ARRAYBUFFERVIEW_INT32 = 4 | ARRAYBUFFERVIEW_SIGNED,
ARRAYBUFFERVIEW_FLOAT32 = 4 | ARRAYBUFFERVIEW_FLOAT,
ARRAYBUFFERVIEW_FLOAT64 = 8 | ARRAYBUFFERVIEW_FLOAT,
} PACKED_FLAGS JsVarDataArrayBufferViewType;
#define JSV_ARRAYBUFFER_GET_SIZE(T) ((T)&ARRAYBUFFERVIEW_MASK_SIZE)
#define JSV_ARRAYBUFFER_IS_SIGNED(T) (((T)&ARRAYBUFFERVIEW_SIGNED)!=0)
#define JSV_ARRAYBUFFER_IS_FLOAT(T) (((T)&ARRAYBUFFERVIEW_FLOAT)!=0)
#define JSV_ARRAYBUFFER_MAX_LENGTH 65535
typedef struct {
unsigned short byteOffset;
unsigned short length;
JsVarDataArrayBufferViewType type;
} PACKED_FLAGS JsVarDataArrayBufferView;
typedef union {
char str[JSVAR_DATA_STRING_LEN]; ///< The contents of this variable if it is a string
/* NOTE: For str above, we INTENTIONALLY OVERFLOW str (and hence data) in the case of STRING_EXTS
* to overwrite 3 references in order to grab another 6 bytes worth of string data */
// TODO do some magic with union/structs in order to make sure we don't intentionally write off the end of arrays
JsVarInt integer; ///< The contents of this variable if it is an int
JsVarFloat floating; ///< The contents of this variable if it is a double
JsCallback callback; ///< Callback for native functions, or 0
JsVarDataArrayBufferView arraybuffer; ///< information for array buffer views.
} PACKED_FLAGS JsVarData;
typedef struct {
#ifdef LARGE_MEM
JsVarRef this; ///< The reference of this variable itself (so we can get back)
#endif
JsVarFlags flags; ///< the flags determine the type of the variable - int/double/string/etc.
JsVarData varData;
/* NOTE: WE INTENTIONALLY OVERFLOW data in the case of STRING_EXTS
* to overwrite the following 3 references in order to grab another
* 6 bytes worth of string data */
/* For Variable NAMES (e.g. Object/Array keys) these store actual next/previous pointers for a linked list
* For STRING_EXT - extra characters
* Not used for other stuff
*/
JsVarRef nextSibling;
JsVarRef prevSibling;
JsVarRefCounter refs; ///< The number of references held to this - used for automatic garbage collection. NOT USED for STRINGEXT though (it is just extra characters)
/**
* For OBJECT/ARRAY/FUNCTION - this is the first child
* For NAMES and REF - this is a link to the variable it points to
* For STRING_EXT - extra character data (NOT a link)
* For ARRAYBUFFER - a link to a string containing the data for the array buffer *
*/
JsVarRef firstChild;
/**
* For OBJECT/ARRAY/FUNCTION - this is the last child
* For STRINGS/STRING_EXT/NAME+STRING - this is a link to more string data if it is needed
* For REF - this is the 'parent' that the firstChild is a member of
*/
JsVarRef lastChild;
} PACKED_FLAGS JsVar;
/* We have a few different types:
*
* OBJECT/ARRAY - uses firstChild/lastChild to link to NAMEs.
* BUILT-IN OBJECT - as above, but we use varData to store the name as well. This means built in object names must be LESS THAN 8 CHARACTERS
* FUNCTION - uses firstChild/lastChild to link to NAMEs, and callback is used
* NAME - use nextSibling/prevSibling linking to other NAMEs, and firstChild to link to a Variable of some kind
* STRING - use firstChild to link to other STRINGs if String value is too long
* INT/DOUBLE - firstChild never used
*/
static inline unsigned char jsvGetLocks(JsVar *v) { return (unsigned char)((v->flags>>JSV_LOCK_SHIFT) & JSV_LOCK_MAX); }
// For debugging/testing ONLY - maximum # of vars we are allowed to use
void jsvSetMaxVarsUsed(unsigned int size);
// Init/kill vars as a whole
void jsvInit();
void jsvKill();
void jsvSoftInit(); ///< called when loading from flash
void jsvSoftKill(); ///< called when saving to flash
JsVar *jsvFindOrCreateRoot(); ///< Find or create the ROOT variable item - used mainly if recovering from a saved state.
unsigned int jsvGetMemoryUsage(); ///< Get number of memory records (JsVars) used
unsigned int jsvGetMemoryTotal(); ///< Get total amount of memory records
bool jsvIsMemoryFull(); ///< Get whether memory is full or not
void jsvShowAllocated(); ///< Show what is still allocated, for debugging memory problems
/// Try and allocate more memory - only works if RESIZABLE_JSVARS is defined
void jsvSetMemoryTotal(unsigned int jsNewVarCount);
// Note that jsvNew* don't REF a variable for you, but the do LOCK it
JsVar *jsvNew(); ///< Create a new variable
JsVar *jsvNewWithFlags(JsVarFlags flags);
JsVar *jsvNewFromString(const char *str); ///< Create a new string
JsVar *jsvNewStringOfLength(unsigned int byteLength); ///< Create a new string of the given length - full of 0s
static inline JsVar *jsvNewFromEmptyString() { return jsvNewWithFlags(JSV_STRING); } ;///< Create a new empty string
JsVar *jsvNewFromLexer(struct JsLex *lex, JslCharPos charFrom, JslCharPos charTo); // Create a new STRING from part of the lexer
JsVar *jsvNewFromInteger(JsVarInt value);
JsVar *jsvNewFromBool(bool value);
JsVar *jsvNewFromFloat(JsVarFloat value);
// Turns var into a Variable name that links to the given value... No locking so no need to unlock var
JsVar *jsvMakeIntoVariableName(JsVar *var, JsVar *valueOrZero);
JsVar *jsvNewFromPin(int pin);
/// DO NOT CALL THIS DIRECTLY - this frees an unreffed/locked var
void jsvFreePtr(JsVar *var);
/// Get a reference from a var - SAFE for null vars
JsVarRef jsvGetRef(JsVar *var);
/// SCARY - only to be used for vital stuff like load/save
JsVar *_jsvGetAddressOf(JsVarRef ref);
/// Lock this reference and return a pointer - UNSAFE for null refs
JsVar *jsvLock(JsVarRef ref);
/// Lock this pointer and return a pointer - UNSAFE for null pointer
JsVar *jsvLockAgain(JsVar *var);
/// Unlock this variable - this is SAFE for null variables
void jsvUnLock(JsVar *var);
/// Reference - set this variable as used by something
JsVar *jsvRef(JsVar *v);
/// Unreference - set this variable as not used by anything
void jsvUnRef(JsVar *var);
/// Helper fn, Reference - set this variable as used by something
JsVarRef jsvRefRef(JsVarRef ref);
/// Helper fn, Unreference - set this variable as not used by anything
JsVarRef jsvUnRefRef(JsVarRef ref);
static inline bool jsvIsRoot(const JsVar *v) { return v && (v->flags&JSV_VARTYPEMASK)==JSV_ROOT; }
static inline bool jsvIsPin(const JsVar *v) { return v && (v->flags&JSV_VARTYPEMASK)==JSV_PIN; }
static inline bool jsvIsInt(const JsVar *v) { return v && ((v->flags&JSV_VARTYPEMASK)==JSV_INTEGER || (v->flags&JSV_VARTYPEMASK)==JSV_PIN); }
static inline bool jsvIsFloat(const JsVar *v) { return v && (v->flags&JSV_VARTYPEMASK)==JSV_FLOAT; }
static inline bool jsvIsBoolean(const JsVar *v) { return v && (v->flags&JSV_VARTYPEMASK)==JSV_BOOLEAN; }
static inline bool jsvIsString(const JsVar *v) { return v && (v->flags&JSV_VARTYPEMASK)>=JSV_STRING_0 && (v->flags&JSV_VARTYPEMASK)<=JSV_STRING_MAX; }
static inline bool jsvIsStringExt(const JsVar *v) { return v && (v->flags&JSV_VARTYPEMASK)>=JSV_STRING_EXT_0 && (v->flags&JSV_VARTYPEMASK)<=JSV_STRING_EXT_MAX; } ///< The extra bits dumped onto the end of a string to store more data
static inline bool jsvIsNumeric(const JsVar *v) { return v && (v->flags&JSV_VARTYPEMASK)>=JSV_NUMERICSTART && (v->flags&JSV_VARTYPEMASK)<=JSV_NUMERICEND; }
static inline bool jsvIsFunction(const JsVar *v) { return v && (v->flags&JSV_VARTYPEMASK)==JSV_FUNCTION; }
static inline bool jsvIsFunctionParameter(const JsVar *v) { return v && (v->flags&JSV_FUNCTION_PARAMETER) == JSV_FUNCTION_PARAMETER; }
static inline bool jsvIsObject(const JsVar *v) { return v && (((v->flags&JSV_VARTYPEMASK)==JSV_OBJECT) || ((v->flags&JSV_VARTYPEMASK)==JSV_ROOT)); }
static inline bool jsvIsArray(const JsVar *v) { return v && (v->flags&JSV_VARTYPEMASK)==JSV_ARRAY; }
static inline bool jsvIsArrayBuffer(const JsVar *v) { return v && (v->flags&JSV_VARTYPEMASK)==JSV_ARRAYBUFFER; }
static inline bool jsvIsArrayBufferName(const JsVar *v) { return v && (v->flags&(JSV_VARTYPEMASK|JSV_NAME))==JSV_ARRAYBUFFERNAME; }
static inline bool jsvIsNative(const JsVar *v) { return v && (v->flags&JSV_NATIVE)!=0; }
static inline bool jsvIsUndefined(const JsVar *v) { return v==0; }
static inline bool jsvIsNull(const JsVar *v) { return v && (v->flags&JSV_VARTYPEMASK)==JSV_NULL; }
static inline bool jsvIsBasic(const JsVar *v) { return jsvIsNumeric(v) || jsvIsString(v);} ///< Is this *not* an array/object/etc
static inline bool jsvIsName(const JsVar *v) { return v && (v->flags & JSV_NAME)!=0; } ///< NAMEs are what's used to name a variable (it is not the data itself)
static inline bool jsvIsIterable(const JsVar *v) {
return jsvIsArray(v) || jsvIsObject(v) || jsvIsFunction(v) ||
jsvIsString(v) || jsvIsArrayBuffer(v);
}
/** Does this string contain only Numeric characters? */
bool jsvIsStringNumeric(const JsVar *var);
/** Does this string contain only Numeric characters? This is for arrays
* and makes the assertion that int_to_string(string_to_int(var))==var */
bool jsvIsStringNumericStrict(const JsVar *var);
// TODO: maybe isName shouldn't include ArrayBufferName?
bool jsvHasCharacterData(const JsVar *v); ///< does the v->data union contain character data?
bool jsvHasStringExt(const JsVar *v);
/// Does this variable use firstChild/lastChild to point to multiple childrem
bool jsvHasChildren(const JsVar *v);
/// Is this variable a type that uses firstChild to point to a single Variable (ie. it doesn't have multiple children)
bool jsvHasSingleChild(const JsVar *v);
/// Does this variable have a 'ref' argument? Stringexts use it for extra character data
static inline bool jsvHasRef(const JsVar *v) { return !jsvIsStringExt(v); }
/// This is the number of characters a JsVar can contain, NOT string length
static inline size_t jsvGetMaxCharactersInVar(const JsVar *v) {
// see jsvCopy - we need to know about this in there too
if (jsvIsStringExt(v)) return JSVAR_DATA_STRING_MAX_LEN;
assert(jsvHasCharacterData(v));
return JSVAR_DATA_STRING_LEN;
}
/// This is the number of characters a JsVar can contain, NOT string length
static inline size_t jsvGetCharactersInVar(const JsVar *v) {
assert(jsvIsString(v) || jsvIsStringExt(v));
int f = v->flags&JSV_VARTYPEMASK;
return (size_t)(f - ((f < JSV_STRING_EXT_0) ? JSV_STRING_0 : JSV_STRING_EXT_0));
}
/// This is the number of characters a JsVar can contain, NOT string length
static inline void jsvSetCharactersInVar(JsVar *v, size_t chars) {
assert(jsvIsString(v) || jsvIsStringExt(v));
if (jsvIsString(v)) { assert(chars <= JSVAR_DATA_STRING_LEN); }
if (jsvIsStringExt(v)) { assert(chars <= JSVAR_DATA_STRING_MAX_LEN); }
int f = v->flags&JSV_VARTYPEMASK;
v->flags = (JsVarFlags)((v->flags&(~JSV_VARTYPEMASK)) | (((f < JSV_STRING_EXT_0) ? JSV_STRING_0 : JSV_STRING_EXT_0) + (int)chars));
}
/** Check if two Basic Variables are equal (this IGNORES the value that is pointed to,
* so 'a=5'=='a=7' but 'a=5'!='b=5')
*/
bool jsvIsBasicVarEqual(JsVar *a, JsVar *b);
/** Check if two things are equal. Basic vars are done by value,
* for anything else the reference/pointer must be equal */
bool jsvIsEqual(JsVar *a, JsVar *b);
const char *jsvGetConstString(const JsVar *v); ///< Get a const string representing this variable - if we can. Otherwise return 0
const char *jsvGetTypeOf(const JsVar *v); ///< Return the 'type' of the JS variable (eg. JS's typeof operator)
size_t jsvGetString(const JsVar *v, char *str, size_t len); ///< Save this var as a string to the given buffer, and return how long it was (return val doesn't include terminating 0)
void jsvSetString(JsVar *v, char *str, size_t len); ///< Set the Data in this string. This must JUST overwrite - not extend or shrink
JsVar *jsvAsString(JsVar *var, bool unlockVar); ///< If var is a string, lock and return it, else create a new string
size_t jsvGetStringLength(JsVar *v); ///< Get the length of this string, IF it is a string
int jsvGetLinesInString(JsVar *v); ///< IN A STRING get the number of lines in the string (min=1)
int jsvGetCharsOnLine(JsVar *v, int line); ///< IN A STRING Get the number of characters on a line - lines start at 1
void jsvGetLineAndCol(JsVar *v, int charIdx, int* line, int *col); ///< IN A STRING, get the line and column of the given character. Both values must be non-null
int jsvGetIndexFromLineAndCol(JsVar *v, int line, int col); ///< IN A STRING, get a character index from a line and column
bool jsvIsStringEqual(JsVar *var, const char *str);
int jsvCompareString(JsVar *va, JsVar *vb, int starta, int startb, bool equalAtEndOfString); ///< Compare 2 strings, starting from the given character positions
int jsvCompareInteger(JsVar *va, JsVar *vb); ///< Compare 2 integers, >0 if va>vb, <0 if va<vb. If compared with a non-integer, that gets put later
void jsvAppendString(JsVar *var, const char *str); ///< Append the given string to this one
void jsvAppendStringBuf(JsVar *var, const char *str, int length); ///< Append the given string to this one - but does not use null-terminated strings
void jsvAppendPrintf(JsVar *var, const char *fmt, ...); ///< Append the formatted string to a variable (see vcbprintf)
static inline void jsvAppendCharacter(JsVar *var, char ch) { jsvAppendStringBuf(var, &ch, 1); }; ///< Append the given character to this string
#define JSVAPPENDSTRINGVAR_MAXLENGTH (0x7FFFFFFF)
void jsvAppendStringVar(JsVar *var, const JsVar *str, int stridx, int maxLength); ///< Append str to var. Both must be strings. stridx = start char or str, maxLength = max number of characters (can be JSVAPPENDSTRINGVAR_MAXLENGTH). stridx can be negative to go from end of string
void jsvAppendStringVarComplete(JsVar *var, const JsVar *str); ///< Append all of str to var. Both must be strings.
char jsvGetCharInString(JsVar *v, int idx);
JsVarInt jsvGetInteger(const JsVar *v);
void jsvSetInteger(JsVar *v, JsVarInt value); ///< Set an integer value (use carefully!)
JsVarFloat jsvGetFloat(const JsVar *v); ///< Get the floating point representation of this var
bool jsvGetBool(const JsVar *v);
JsVar *jsvAsNumber(JsVar *var); ///< Convert the given variable to a number
static inline JsVarInt _jsvGetIntegerAndUnLock(JsVar *v) { JsVarInt i = jsvGetInteger(v); jsvUnLock(v); return i; }
static inline JsVarFloat _jsvGetFloatAndUnLock(JsVar *v) { JsVarFloat f = jsvGetFloat(v); jsvUnLock(v); return f; }
static inline bool _jsvGetBoolAndUnLock(JsVar *v) { bool b = jsvGetBool(v); jsvUnLock(v); return b; }
#ifdef SAVE_ON_FLASH
JsVarInt jsvGetIntegerAndUnLock(JsVar *v);
JsVarFloat jsvGetFloatAndUnLock(JsVar *v);
bool jsvGetBoolAndUnLock(JsVar *v);
#else
#define jsvGetIntegerAndUnLock _jsvGetIntegerAndUnLock
#define jsvGetFloatAndUnLock _jsvGetFloatAndUnLock
#define jsvGetBoolAndUnLock _jsvGetBoolAndUnLock
#endif
/** Get the item at the given location in the array buffer and return the result */
size_t jsvGetArrayBufferLength(JsVar *arrayBuffer);
/** Get the item at the given location in the array buffer and return the result */
JsVar *jsvArrayBufferGet(JsVar *arrayBuffer, JsVarInt index);
/** Set the item at the given location in the array buffer */
void jsvArrayBufferSet(JsVar *arrayBuffer, JsVarInt index, JsVar *value);
/** Given an integer name that points to an arraybuffer or an arraybufferview, evaluate it and return the result */
JsVar *jsvArrayBufferGetFromName(JsVar *name);
/** If a is a name skip it and go to what it points to - and so on.
* ALWAYS locks - so must unlock what it returns. It MAY
* return 0. */
JsVar *jsvSkipName(JsVar *a);
/** If a is a name skip it and go to what it points to.
* ALWAYS locks - so must unlock what it returns. It MAY
* return 0. */
JsVar *jsvSkipOneName(JsVar *a);
/** If a is a's child is a name skip it and go to what it points to.
* ALWAYS locks - so must unlock what it returns. */
JsVar *jsvSkipToLastName(JsVar *a);
/** Same as jsvSkipName, but ensures that 'a' is unlocked if it was
* a name, so it can be used INLINE_FUNC */
static inline JsVar *jsvSkipNameAndUnLock(JsVar *a) {
JsVar *b = jsvSkipName(a);
jsvUnLock(a);
return b;
}
/** Same as jsvSkipOneName, but ensures that 'a' is unlocked if it was
* a name, so it can be used INLINE_FUNC */
static inline JsVar *jsvSkipOneNameAndUnLock(JsVar *a) {
JsVar *b = jsvSkipOneName(a);
jsvUnLock(a);
return b;
}
/// MATHS!
JsVar *jsvMathsOpSkipNames(JsVar *a, JsVar *b, int op);
JsVar *jsvMathsOp(JsVar *a, JsVar *b, int op);
/// Negates an integer/double value
JsVar *jsvNegateAndUnLock(JsVar *v);
/// Copy this variable and return the locked copy
JsVar *jsvCopy(JsVar *src);
/** Copy only a name, not what it points to. ALTHOUGH the link to what it points to is maintained unless linkChildren=false.
If keepAsName==false, this will be converted into a normal variable */
JsVar *jsvCopyNameOnly(JsVar *src, bool linkChildren, bool keepAsName);
/// Tree related stuff
void jsvAddName(JsVar *parent, JsVar *nameChild); // Add a child, which is itself a name
JsVar *jsvAddNamedChild(JsVar *parent, JsVar *child, const char *name); // Add a child, and create a name for it. Returns a LOCKED var. DOES NOT CHECK FOR DUPLICATES
JsVar *jsvSetNamedChild(JsVar *parent, JsVar *child, const char *name); // Add a child, and create a name for it. Returns a LOCKED name var. CHECKS FOR DUPLICATES
JsVar *jsvSetValueOfName(JsVar *name, JsVar *src); // Set the value of a child created with jsvAddName,jsvAddNamedChild. Returns the UNLOCKED name argument
JsVar *jsvFindChildFromString(JsVar *parent, const char *name, bool createIfNotFound); // Non-recursive finding of child with name. Returns a LOCKED var
JsVar *jsvFindChildFromVar(JsVar *parent, JsVar *childName, bool addIfNotFound); // Non-recursive finding of child with name. Returns a LOCKED var
static inline JsVar *jsvFindChildFromStringRef(JsVarRef parentref, const char *name, bool addIfNotFound) { // Non-recursive finding of child with name. Returns a LOCKED var
JsVar *p = jsvLock(parentref);
JsVar *v = jsvFindChildFromString(p, name, addIfNotFound);
jsvUnLock(p);
return v;
}
static inline JsVar *jsvFindChildFromVarRef(JsVarRef parentref, JsVar *childName, bool addIfNotFound) { // Non-recursive finding of child with name. Returns a LOCKED var
JsVar *p = jsvLock(parentref);
JsVar *v = jsvFindChildFromVar(p, childName, addIfNotFound);
jsvUnLock(p);
return v;
}
/// Remove a child - note that the child MUST ACTUALLY BE A CHILD!
void jsvRemoveChild(JsVar *parent, JsVar *child);
void jsvRemoveAllChildren(JsVar *parent);
static inline void jsvRemoveNamedChild(JsVar *parent, const char *name) {
JsVar *child = jsvFindChildFromString(parent, name, false);
if (child) {
jsvRemoveChild(parent, child);
jsvUnLock(child);
}
}
/// Get the named child of an object. If createChild!=0 then create the child
JsVar *jsvObjectGetChild(JsVar *obj, const char *name, JsVarFlags createChild);
/// Set the named child of an object, and return the child (so you can choose to unlock it if you want)
JsVar *jsvObjectSetChild(JsVar *obj, const char *name, JsVar *child);
int jsvGetChildren(JsVar *v); ///< number of children of a variable. also see jsvGetArrayLength and jsvGetLength
JsVarInt jsvGetArrayLength(JsVar *arr); ///< Not the same as GetChildren, as it can be a sparse array
JsVarInt jsvGetLength(JsVar *src); ///< General purpose length function. Does the 'right' thing
size_t jsvCountJsVarsUsed(JsVar *v); ///< Count the amount of JsVars used. Mostly useful for debugging
JsVar *jsvGetArrayItem(JsVar *arr, int index); ///< Get an item at the specified index in the array (and lock it)
JsVar *jsvGetArrayIndexOf(JsVar *arr, JsVar *value, bool matchExact); ///< Get the index of the value in the array (matchExact==use pointer, not equality check)
JsVarInt jsvArrayPushWithInitialSize(JsVar *arr, JsVar *value, JsVarInt initialValue); ///< Adds new elements to the end of an array, and returns the new length. initialValue is the item index when no items are currently in the array.
JsVarInt jsvArrayPush(JsVar *arr, JsVar *value); ///< Adds a new element to the end of an array, and returns the new length
JsVarInt jsvArrayPushAndUnLock(JsVar *arr, JsVar *value); ///< Adds a new element to the end of an array, unlocks it, and returns the new length
JsVar *jsvArrayPop(JsVar *arr); ///< Removes the last element of an array, and returns that element (or 0 if empty). includes the NAME
JsVar *jsvArrayPopFirst(JsVar *arr); ///< Removes the first element of an array, and returns that element (or 0 if empty) includes the NAME
JsVar *jsvArrayGetLast(JsVar *arr); ///< Get the last element of an array (does not remove, unlike jsvArrayPop), and returns that element (or 0 if empty) includes the NAME
JsVar *jsvArrayJoin(JsVar *arr, JsVar *filler); ///< Join all elements of an array together into a string
void jsvArrayInsertBefore(JsVar *arr, JsVar *beforeIndex, JsVar *element); ///< Insert a new element before beforeIndex, DOES NOT UPDATE INDICES
static inline bool jsvArrayIsEmpty(JsVar *arr) { assert(jsvIsArray(arr)); return !arr->firstChild; } ///< Return true is array is empty
/** Write debug info for this Var out to the console */
void jsvTrace(JsVarRef ref, int indent);
/** Run a garbage collection sweep - return true if things have been freed */
bool jsvGarbageCollect();
/** Remove whitespace to the right of a string - on MULTIPLE LINES */
JsVar *jsvStringTrimRight(JsVar *srcString);
/** If v is the key of a function, return true if it is internal and shouldn't be visible to the user */
bool jsvIsInternalFunctionKey(JsVar *v);
/// If v is the key of an object, return true if it is internal and shouldn't be visible to the user
bool jsvIsInternalObjectKey(JsVar *v);
// --------------------------------------------------------------------------------------------
typedef struct JsvStringIterator {
size_t charIdx; ///< index of character in var
size_t charsInVar; ///< total characters in var
size_t index; ///< index in string
JsVar *var; ///< current StringExt we're looking at
} JsvStringIterator;
// slight hack to enure we can use string iterator with const JsVars
#define jsvStringIteratorNewConst(it,str,startIdx) jsvStringIteratorNew(it,(JsVar*)str,startIdx)
void jsvStringIteratorNew(JsvStringIterator *it, JsVar *str, int startIdx);
/// Gets the current character (or 0)
static inline char jsvStringIteratorGetChar(JsvStringIterator *it) {
if (!it->var) return 0;
return it->var->varData.str[it->charIdx];
}
/// Gets the current (>=0) character (or -1)
static inline int jsvStringIteratorGetCharOrMinusOne(JsvStringIterator *it) {
if (!it->var) return -1;
return (int)(unsigned char)it->var->varData.str[it->charIdx];
}
/// Do we have a character, or are we at the end?
static inline bool jsvStringIteratorHasChar(JsvStringIterator *it) {
return it->charIdx < it->charsInVar;
}
/// Sets a character (will not extend the string - just overwrites)
static inline void jsvStringIteratorSetChar(JsvStringIterator *it, char c) {
if (jsvStringIteratorHasChar(it))
it->var->varData.str[it->charIdx] = c;
}
/// Gets the current index in the string
static inline size_t jsvStringIteratorGetIndex(JsvStringIterator *it) {
return it->index;
}
/// Move to next character
void jsvStringIteratorNext(JsvStringIterator *it);
/// Move to next character (this one is inlined where speed is needed)
static inline void jsvStringIteratorNextInline(JsvStringIterator *it) {
it->charIdx++;
it->index++;
if (it->charIdx >= it->charsInVar) {
it->charIdx -= it->charsInVar;
if (it->var && it->var->lastChild) {
JsVar *next = jsvLock(it->var->lastChild);
jsvUnLock(it->var);
it->var = next;
it->charsInVar = jsvGetCharactersInVar(it->var);
} else {
jsvUnLock(it->var);
it->var = 0;
it->charsInVar = 0;
}
}
}
/// Go to the end of the string iterator - for use with jsvStringIteratorAppend
void jsvStringIteratorGotoEnd(JsvStringIterator *it);
/// Append a character TO THE END of a string iterator
void jsvStringIteratorAppend(JsvStringIterator *it, char ch);
static inline void jsvStringIteratorFree(JsvStringIterator *it) {
jsvUnLock(it->var);
}
// --------------------------------------------------------------------------------------------
typedef struct JsArrayIterator {
JsVar *var;
} JsArrayIterator;
static inline void jsvArrayIteratorNew(JsArrayIterator *it, JsVar *arr) {
assert(jsvIsArray(arr));
it->var = arr->firstChild ? jsvLock(arr->firstChild) : 0;
}
/// Gets the current array element (or 0)
static inline JsVar *jsvArrayIteratorGetElement(JsArrayIterator *it) {
if (!it->var) return 0; // end of array
return it->var->firstChild ? jsvLock(it->var->firstChild) : 0; // might even be undefined
}
/// Gets the current array element index (or 0)
static inline JsVar *jsvArrayIteratorGetIndex(JsArrayIterator *it) {
if (!it->var) return 0;
return jsvLockAgain(it->var);
}
/// Do we have a character, or are we at the end?
static inline bool jsvArrayIteratorHasElement(JsArrayIterator *it) {
return it->var != 0;
}
/// Move to next character
static inline void jsvArrayIteratorNext(JsArrayIterator *it) {
if (it->var) {
JsVarRef next = it->var->nextSibling;
jsvUnLock(it->var);
it->var = next ? jsvLock(next) : 0;
}
}
static inline void jsvArrayIteratorFree(JsArrayIterator *it) {
jsvUnLock(it->var);
}
// --------------------------------------------------------------------------------------------
typedef struct JsObjectIterator {
JsVar *var;
} JsObjectIterator;
static inline void jsvObjectIteratorNew(JsObjectIterator *it, JsVar *obj) {
assert(jsvIsObject(obj) || jsvIsFunction(obj));
it->var = obj->firstChild ? jsvLock(obj->firstChild) : 0;
}
/// Gets the current object element key (or 0)
static inline JsVar *jsvObjectIteratorGetKey(JsObjectIterator *it) {
if (!it->var) return 0; // end of object
return jsvLockAgain(it->var);
}
/// Gets the current object element value (or 0)
static inline JsVar *jsvObjectIteratorGetValue(JsObjectIterator *it) {
if (!it->var) return 0; // end of object
return it->var->firstChild ? jsvLock(it->var->firstChild) : 0; // might even be undefined
}
/// Do we have a key, or are we at the end?
static inline bool jsvObjectIteratorHasElement(JsObjectIterator *it) {
return it->var != 0;
}
/// Move to next character
static inline void jsvObjectIteratorNext(JsObjectIterator *it) {
if (it->var) {
JsVarRef next = it->var->nextSibling;
jsvUnLock(it->var);
it->var = next ? jsvLock(next) : 0;
}
}
static inline void jsvObjectIteratorFree(JsObjectIterator *it) {
jsvUnLock(it->var);
}
// --------------------------------------------------------------------------------------------
typedef struct JsvArrayBufferIterator {
JsvStringIterator it;
JsVarDataArrayBufferViewType type;
JsVarInt byteLength;
JsVarInt byteOffset;
JsVarInt index;
bool hasAccessedElement;
} JsvArrayBufferIterator;
void jsvArrayBufferIteratorNew(JsvArrayBufferIterator *it, JsVar *arrayBuffer, JsVarInt index);
JsVar *jsvArrayBufferIteratorGetValue(JsvArrayBufferIterator *it);
JsVarInt jsvArrayBufferIteratorGetIntegerValue(JsvArrayBufferIterator *it);
JsVarFloat jsvArrayBufferIteratorGetFloatValue(JsvArrayBufferIterator *it);
void jsvArrayBufferIteratorSetValue(JsvArrayBufferIterator *it, JsVar *value);
void jsvArrayBufferIteratorSetIntegerValue(JsvArrayBufferIterator *it, JsVarInt value);
JsVar* jsvArrayBufferIteratorGetIndex(JsvArrayBufferIterator *it);
bool jsvArrayBufferIteratorHasElement(JsvArrayBufferIterator *it);
void jsvArrayBufferIteratorNext(JsvArrayBufferIterator *it);
void jsvArrayBufferIteratorFree(JsvArrayBufferIterator *it);
// --------------------------------------------------------------------------------------------
union JsvIteratorUnion {
JsvStringIterator str;
JsObjectIterator obj;
JsArrayIterator arr;
JsvArrayBufferIterator buf;
};
/** General Purpose iterator, for Strings, Arrays, Objects, Typed Arrays */
typedef struct JsvIterator {
enum {JSVI_STRING, JSVI_ARRAY, JSVI_OBJECT, JSVI_ARRAYBUFFER } type;
union JsvIteratorUnion it;
} JsvIterator;
void jsvIteratorNew(JsvIterator *it, JsVar *obj);
JsVar *jsvIteratorGetKey(JsvIterator *it);
JsVar *jsvIteratorGetValue(JsvIterator *it);
JsVarInt jsvIteratorGetIntegerValue(JsvIterator *it);
bool jsvIteratorHasElement(JsvIterator *it);
void jsvIteratorNext(JsvIterator *it);
void jsvIteratorFree(JsvIterator *it);
#endif /* JSVAR_H_ */

View File

@@ -0,0 +1,328 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* This file is designed to be parsed during the build process
*
* JavaScript methods for Arrays
* ----------------------------------------------------------------------------
*/
#include "jswrap_array.h"
#include "jsparse.h"
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))
/*JSON{ "type":"class",
"class" : "Array",
"check" : "jsvIsArray(var)",
"description" : ["This is the built-in JavaScript class for arrays.",
"Arrays can be defined with ```[]```, ```new Array()```, or ```new Array(length)```" ]
}*/
/*JSON{ "type":"constructor", "class": "Array", "name": "Array",
"description" : "Create an Array. Either give it one integer argument (>=0) which is the length of the array, or any number of arguments ",
"generate" : "jswrap_array_constructor",
"params" : [ [ "args", "JsVarArray", "The length of the array OR any number of items to add to the array" ] ],
"return" : [ "JsVar", "An Array" ]
}*/
JsVar *jswrap_array_constructor(JsVar *args) {
assert(args);
if (jsvGetArrayLength(args)==1) {
JsVar *firstArg = jsvSkipNameAndUnLock(jsvArrayGetLast(args)); // also the first!
if (jsvIsInt(firstArg) && jsvGetInteger(firstArg)>=0) {
JsVarInt count = jsvGetInteger(firstArg);
// we cheat - no need to fill the array - just the last element
if (count>0) {
JsVar *arr = jsvNewWithFlags(JSV_ARRAY);
if (!arr) return 0; // out of memory
JsVar *idx = jsvMakeIntoVariableName(jsvNewFromInteger(count-1), 0);
if (idx) { // could be out of memory
jsvAddName(arr, idx);
jsvUnLock(idx);
}
jsvUnLock(firstArg);
return arr;
}
}
jsvUnLock(firstArg);
}
// Otherwise, we just return the array!
return jsvLockAgain(args);
}
/*JSON{ "type":"method", "class": "Array", "name" : "contains",
"description" : "Return true if this array contains the given value",
"generate" : "jswrap_array_contains",
"params" : [ [ "value", "JsVar", "The value to check for"] ],
"return" : ["bool", "Whether value is in the array or not"]
}*/
bool jswrap_array_contains(JsVar *parent, JsVar *value) {
// ArrayIndexOf will return 0 if not found
JsVar *arrElement = jsvGetArrayIndexOf(parent, value, false/*not exact*/);
bool contains = arrElement!=0;
jsvUnLock(arrElement);
return contains;
}
/*JSON{ "type":"method", "class": "Array", "name" : "indexOf",
"description" : "Return the index of the value in the array, or -1",
"generate" : "jswrap_array_indexOf",
"params" : [ [ "value", "JsVar", "The value to check for"] ],
"return" : ["JsVar", "the index of the value in the array, or -1"]
}*/
JsVar *jswrap_array_indexOf(JsVar *parent, JsVar *value) {
JsVar *idxName = jsvGetArrayIndexOf(parent, value, false/*not exact*/);
// but this is the name - we must turn it into a var
if (idxName == 0) return jsvNewFromInteger(-1); // not found!
JsVar *idx = jsvCopyNameOnly(idxName, false/* no children */, false/* Make sure this is not a name*/);
jsvUnLock(idxName);
return idx;
}
/*JSON{ "type":"method", "class": "Array", "name" : "join",
"description" : "Join all elements of this array together into one string, using 'separator' between them. eg. ```[1,2,3].join(' ')=='1 2 3'```",
"generate" : "jswrap_array_join",
"params" : [ [ "separator", "JsVar", "The separator"] ],
"return" : ["JsVar", "A String representing the Joined array"]
}*/
JsVar *jswrap_array_join(JsVar *parent, JsVar *filler) {
if (jsvIsUndefined(filler))
filler = jsvNewFromString(","); // the default it seems
else
filler = jsvAsString(filler, false);
if (!filler) return 0; // out of memory
JsVar *str = jsvArrayJoin(parent, filler);
jsvUnLock(filler);
return str;
}
/*JSON{ "type":"method", "class": "Array", "name" : "push",
"description" : "Push a new value onto the end of this array'",
"generate_full" : "jsvArrayPush(parent, value)",
"params" : [ [ "value", "JsVar", "The value to add"] ],
"return" : ["int", "The new size of the array"]
}*/
/*JSON{ "type":"method", "class": "Array", "name" : "pop",
"description" : "Pop a new value off of the end of this array",
"generate_full" : "jsvArrayPop(parent)",
"return" : ["JsVar", "The value that is popped off"]
}*/
JsVar *_jswrap_array_map_or_forEach(JsVar *parent, JsVar *funcVar, JsVar *thisVar, bool isMap) {
if (!jsvIsFunction(funcVar)) {
jsError("Array.map's first argument should be a function");
return 0;
}
if (!jsvIsUndefined(thisVar) && !jsvIsObject(thisVar)) {
jsError("Arraymap's second argument should be undefined, or an object");
return 0;
}
JsVar *array = 0;
if (isMap)
array = jsvNewWithFlags(JSV_ARRAY);
if (array || !isMap) {
JsVarRef childRef = parent->firstChild;
while (childRef) {
JsVar *child = jsvLock(childRef);
if (jsvIsInt(child)) {
JsVar *args[3], *mapped;
args[0] = jsvLock(child->firstChild);
// child is a variable name, create a new variable for the index
args[1] = jsvNewFromInteger(jsvGetInteger(child));
args[2] = parent;
mapped = jspeFunctionCall(funcVar, 0, thisVar, false, 3, args);
jsvUnLock(args[0]);
jsvUnLock(args[1]);
if (mapped) {
if (isMap) {
JsVar *name = jsvCopyNameOnly(child, false/*linkChildren*/, true/*keepAsName*/);
if (name) { // out of memory?
name->firstChild = jsvGetRef(jsvRef(mapped));
jsvAddName(array, name);
jsvUnLock(name);
}
}
jsvUnLock(mapped);
}
}
childRef = child->nextSibling;
jsvUnLock(child);
}
}
return array;
}
/*JSON{ "type":"method", "class": "Array", "name" : "map",
"description" : "Return an array which is made from the following: ```A.map(function) = [function(A[0]), function(A[1]), ...]```",
"generate" : "jswrap_array_map",
"params" : [ [ "function", "JsVar", "Function used to map one item to another"] ,
[ "thisArg", "JsVar", "if specified, the function is called with 'this' set to thisArg (optional)"] ],
"return" : ["JsVar", "The value that is popped off"]
}*/
JsVar *jswrap_array_map(JsVar *parent, JsVar *funcVar, JsVar *thisVar) {
return _jswrap_array_map_or_forEach(parent, funcVar, thisVar, true);
}
/*JSON{ "type":"method", "class": "Array", "name" : "splice",
"description" : "Both remove and add items to an array",
"generate" : "jswrap_array_splice",
"params" : [ [ "index", "int", "Index at which to start changing the array. If negative, will begin that many elements from the end"],
[ "howMany", "JsVar", "An integer indicating the number of old array elements to remove. If howMany is 0, no elements are removed."],
[ "element1", "JsVar", "A new item to add (optional)" ],
[ "element2", "JsVar", "A new item to add (optional)" ],
[ "element3", "JsVar", "A new item to add (optional)" ],
[ "element4", "JsVar", "A new item to add (optional)" ],
[ "element5", "JsVar", "A new item to add (optional)" ],
[ "element6", "JsVar", "A new item to add (optional)" ] ],
"return" : ["JsVar", "An array containing the removed elements. If only one element is removed, an array of one element is returned."]
}*/
JsVar *jswrap_array_splice(JsVar *parent, JsVarInt index, JsVar *howManyVar, JsVar *element1, JsVar *element2, JsVar *element3, JsVar *element4, JsVar *element5, JsVar *element6) {
JsVarInt len = jsvGetArrayLength(parent);
if (index<0) index+=len;
if (index<0) index=0;
if (index>len) index=len;
JsVarInt howMany = len; // how many to delete!
if (jsvIsInt(howManyVar)) howMany = jsvGetInteger(howManyVar);
if (howMany > len-index) howMany = len-index;
JsVarInt newItems = 0;
if (element1) newItems++;
if (element2) newItems++;
if (element3) newItems++;
if (element4) newItems++;
if (element5) newItems++;
if (element6) newItems++;
JsVarInt shift = newItems-howMany;
bool needToAdd = false;
JsVar *result = jsvNewWithFlags(JSV_ARRAY);
JsArrayIterator it;
jsvArrayIteratorNew(&it, parent);
while (jsvArrayIteratorHasElement(&it) && !needToAdd) {
bool goToNext = true;
JsVar *idxVar = jsvArrayIteratorGetIndex(&it);
if (idxVar && jsvIsInt(idxVar)) {
JsVarInt idx = jsvGetInteger(idxVar);
if (idx<index) {
// do nothing...
} else if (idx<index+howMany) { // must delete
if (result) { // append to result array
JsVar *el = jsvArrayIteratorGetElement(&it);
jsvArrayPushAndUnLock(result, el);
}
// delete
goToNext = false;
JsVar *toRemove = jsvArrayIteratorGetIndex(&it);
jsvArrayIteratorNext(&it);
jsvRemoveChild(parent, toRemove);
jsvUnLock(toRemove);
} else { // we're greater than the amount we need to remove now
needToAdd = true;
goToNext = false;
}
}
jsvUnLock(idxVar);
if (goToNext) jsvArrayIteratorNext(&it);
}
// now we add everything
JsVar *beforeIndex = jsvArrayIteratorGetIndex(&it);
if (element1) jsvArrayInsertBefore(parent, beforeIndex, element1);
if (element2) jsvArrayInsertBefore(parent, beforeIndex, element2);
if (element3) jsvArrayInsertBefore(parent, beforeIndex, element3);
if (element4) jsvArrayInsertBefore(parent, beforeIndex, element4);
if (element5) jsvArrayInsertBefore(parent, beforeIndex, element5);
if (element6) jsvArrayInsertBefore(parent, beforeIndex, element6);
jsvUnLock(beforeIndex);
// And finally renumber
while (jsvArrayIteratorHasElement(&it)) {
JsVar *idxVar = jsvArrayIteratorGetIndex(&it);
if (idxVar && jsvIsInt(idxVar)) {
jsvSetInteger(idxVar, jsvGetInteger(idxVar)+shift);
}
jsvUnLock(idxVar);
jsvArrayIteratorNext(&it);
}
// free
jsvArrayIteratorFree(&it);
return result;
}
/*JSON{ "type":"method", "class": "Array", "name" : "slice",
"description" : "Return a copy of a portion of the calling array",
"generate" : "jswrap_array_slice",
"params" : [ [ "start", "JsVar", "Start index"],
[ "end", "JsVar", "End index (optional)"] ],
"return" : ["JsVar", "A new array"]
}*/
JsVar *jswrap_array_slice(JsVar *parent, JsVar *startVar, JsVar *endVar) {
JsVarInt len = jsvGetArrayLength(parent);
JsVarInt start = 0;
JsVarInt end = len;
if (!jsvIsUndefined(startVar))
start = jsvGetInteger(startVar);
if (!jsvIsUndefined(endVar))
end = jsvGetInteger(endVar);
JsVarInt k = 0;
JsVarInt final = len;
JsVar *array = jsvNewWithFlags(JSV_ARRAY);
if (!array) return 0;
if (start<0) k = max((len + start), 0);
else k = min(start, len);
if (end<0) final = max((len + end), 0);
else final = min(end, len);
bool isDone = false;
JsArrayIterator it;
jsvArrayIteratorNew(&it, parent);
while (jsvArrayIteratorHasElement(&it) && !isDone) {
JsVarInt idx = jsvGetInteger(jsvArrayIteratorGetIndex(&it));
if (idx < k) {
jsvArrayIteratorNext(&it);
} else {
if (k < final) {
jsvArrayPushAndUnLock(array, jsvArrayIteratorGetElement(&it));
jsvArrayIteratorNext(&it);
k++;
} else {
isDone = true;
}
}
}
jsvArrayIteratorFree(&it);
return array;
}
/*JSON{ "type":"method", "class": "Array", "name" : "forEach",
"description" : "Executes a provided function once per array element.",
"generate" : "jswrap_array_forEach",
"params" : [ [ "function", "JsVar", "Function to be executed"] ,
[ "thisArg", "JsVar", "if specified, the function is called with 'this' set to thisArg (optional)"] ]
}*/
void jswrap_array_forEach(JsVar *parent, JsVar *funcVar, JsVar *thisVar) {
_jswrap_array_map_or_forEach(parent, funcVar, thisVar, false);
}

View File

@@ -0,0 +1,23 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* JavaScript methods for Arrays
* ----------------------------------------------------------------------------
*/
#include "jsvar.h"
JsVar *jswrap_array_constructor(JsVar *args);
bool jswrap_array_contains(JsVar *parent, JsVar *value);
JsVar *jswrap_array_indexOf(JsVar *parent, JsVar *value);
JsVar *jswrap_array_join(JsVar *parent, JsVar *filler);
JsVar *jswrap_array_map(JsVar *parent, JsVar *funcVar, JsVar *thisVar);
JsVar *jswrap_array_slice(JsVar *parent, JsVar *startVar, JsVar *endVar);
JsVar *jswrap_array_splice(JsVar *parent, JsVarInt index, JsVar *howManyVar, JsVar *element1, JsVar *element2, JsVar *element3, JsVar *element4, JsVar *element5, JsVar *element6);
void jswrap_array_forEach(JsVar *parent, JsVar *funcVar, JsVar *thisVar);

View File

@@ -0,0 +1,315 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* This file is designed to be parsed during the build process
*
* JavaScript methods for ArrayBuffers
* ----------------------------------------------------------------------------
*/
#include "jswrap_arraybuffer.h"
#include "jsparse.h"
#include "jsinteractive.h"
/*JSON{ "type":"class",
"class" : "ArrayBuffer",
"check" : "jsvIsArrayBuffer(var) && var->varData.arraybuffer.type==ARRAYBUFFERVIEW_ARRAYBUFFER",
"not_real_object" : "Don't treat this as a real object - it's handled differently internally",
"description" : ["This is the built-in JavaScript class for array buffers." ]
}*/
/*JSON{ "type":"class",
"class" : "ArrayBufferView",
"description" : ["This is the built-in JavaScript class that is the prototype for Uint8Array / Float32Array / etc" ]
}*/
/*JSON{ "type":"class",
"class" : "Uint8Array", "prototype" : "ArrayBufferView",
"check" : "jsvIsArrayBuffer(var) && var->varData.arraybuffer.type==ARRAYBUFFERVIEW_UINT8",
"not_real_object" : "Don't treat this as a real object - it's handled differently internally",
"description" : ["This is the built-in JavaScript class for a typed array.",
"Instantiate this in order to efficiently store arrays of data (Espruino's normal arrays store data in a map, which is inefficient for non-sparse arrays). " ]
}*/
/*JSON{ "type":"class",
"class" : "Int8Array", "prototype" : "ArrayBufferView",
"check" : "jsvIsArrayBuffer(var) && var->varData.arraybuffer.type==ARRAYBUFFERVIEW_INT8",
"not_real_object" : "Don't treat this as a real object - it's handled differently internally",
"description" : ["This is the built-in JavaScript class for a typed array.",
"Instantiate this in order to efficiently store arrays of data (Espruino's normal arrays store data in a map, which is inefficient for non-sparse arrays). " ]
}*/
/*JSON{ "type":"class",
"class" : "Uint16Array", "prototype" : "ArrayBufferView",
"check" : "jsvIsArrayBuffer(var) && var->varData.arraybuffer.type==ARRAYBUFFERVIEW_UINT16",
"not_real_object" : "Don't treat this as a real object - it's handled differently internally",
"description" : ["This is the built-in JavaScript class for a typed array.",
"Instantiate this in order to efficiently store arrays of data (Espruino's normal arrays store data in a map, which is inefficient for non-sparse arrays). " ]
}*/
/*JSON{ "type":"class",
"class" : "Int16Array", "prototype" : "ArrayBufferView",
"check" : "jsvIsArrayBuffer(var) && var->varData.arraybuffer.type==ARRAYBUFFERVIEW_INT16",
"not_real_object" : "Don't treat this as a real object - it's handled differently internally",
"description" : ["This is the built-in JavaScript class for a typed array.",
"Instantiate this in order to efficiently store arrays of data (Espruino's normal arrays store data in a map, which is inefficient for non-sparse arrays). " ]
}*/
/*JSON{ "type":"class",
"class" : "Uint32Array", "prototype" : "ArrayBufferView",
"check" : "jsvIsArrayBuffer(var) && var->varData.arraybuffer.type==ARRAYBUFFERVIEW_UINT32",
"not_real_object" : "Don't treat this as a real object - it's handled differently internally",
"description" : ["This is the built-in JavaScript class for a typed array.",
"Instantiate this in order to efficiently store arrays of data (Espruino's normal arrays store data in a map, which is inefficient for non-sparse arrays). " ]
}*/
/*JSON{ "type":"class",
"class" : "Int32Array", "prototype" : "ArrayBufferView",
"check" : "jsvIsArrayBuffer(var) && var->varData.arraybuffer.type==ARRAYBUFFERVIEW_INT32",
"not_real_object" : "Don't treat this as a real object - it's handled differently internally",
"description" : ["This is the built-in JavaScript class for a typed array.",
"Instantiate this in order to efficiently store arrays of data (Espruino's normal arrays store data in a map, which is inefficient for non-sparse arrays). " ]
}*/
/*JSON{ "type":"class",
"class" : "Float32Array", "prototype" : "ArrayBufferView",
"check" : "jsvIsArrayBuffer(var) && var->varData.arraybuffer.type==ARRAYBUFFERVIEW_FLOAT32",
"not_real_object" : "Don't treat this as a real object - it's handled differently internally",
"description" : ["This is the built-in JavaScript class for a typed array.",
"Instantiate this in order to efficiently store arrays of data (Espruino's normal arrays store data in a map, which is inefficient for non-sparse arrays). " ]
}*/
/*JSON{ "type":"class",
"class" : "Float64Array", "prototype" : "ArrayBufferView",
"check" : "jsvIsArrayBuffer(var) && var->varData.arraybuffer.type==ARRAYBUFFERVIEW_FLOAT64",
"not_real_object" : "Don't treat this as a real object - it's handled differently internally",
"description" : ["This is the built-in JavaScript class for a typed array.",
"Instantiate this in order to efficiently store arrays of data (Espruino's normal arrays store data in a map, which is inefficient for non-sparse arrays). " ]
}*/
/*JSON{ "type":"constructor", "class": "ArrayBuffer", "name": "ArrayBuffer",
"description" : "Create an Array Buffer object",
"generate" : "jswrap_arraybuffer_constructor",
"params" : [ [ "byteLength", "int", "The length in Bytes" ] ],
"return" : [ "JsVar", "An ArrayBuffer object" ]
}*/
JsVar *jswrap_arraybuffer_constructor(JsVarInt byteLength) {
if (byteLength <= 0 || byteLength>65535) {
jsError("Invalid length for ArrayBuffer\n");
return 0;
}
if (byteLength > JSV_ARRAYBUFFER_MAX_LENGTH) {
jsError("ArrayBuffer too long\n");
return 0;
}
JsVar *arrData = jsvNewStringOfLength((unsigned int)byteLength);
if (!arrData) return 0;
JsVar *arr = jsvNewWithFlags(JSV_ARRAYBUFFER);
if (!arr) {
jsvUnLock(arrData);
return 0;
}
arr->firstChild = jsvGetRef(jsvRef(arrData));
jsvUnLock(arrData);
arr->varData.arraybuffer.type = ARRAYBUFFERVIEW_ARRAYBUFFER;
arr->varData.arraybuffer.byteOffset = 0;
arr->varData.arraybuffer.length = (unsigned short)byteLength;
return arr;
}
/*
* Potential invocations:
* Uint8Array Uint8Array(unsigned long length);
* Uint8Array Uint8Array(TypedArray array);
* Uint8Array Uint8Array(sequence<type> array);
* Uint8Array Uint8Array(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long length);
*/
/*JSON{ "type":"constructor", "class": "Uint8Array", "name": "Uint8Array",
"description" : "Create a typed array based on the given input. Either an existing Array Buffer, an Integer as a Length, or a simple array",
"generate_full" : "jswrap_typedarray_constructor(ARRAYBUFFERVIEW_UINT8, arr, jsvGetInteger(byteOffset), jsvGetInteger(length))",
"params" : [ [ "arr", "JsVar", "The array or typed array to base this off, or an integer which is the array length" ],
[ "byteOffset", "int", "The byte offset in the ArrayBuffer (ONLY IF the first argument was an ArrayBuffer)" ],
[ "length", "int", "The length (ONLY IF the first argument was an ArrayBuffer)" ] ],
"return" : [ "JsVar", "A typed array" ]
}*/
/*JSON{ "type":"constructor", "class": "Int8Array", "name": "Int8Array",
"description" : "Create a typed array based on the given input. Either an existing Array Buffer, an Integer as a Length, or a simple array",
"generate_full" : "jswrap_typedarray_constructor(ARRAYBUFFERVIEW_INT8, arr, jsvGetInteger(byteOffset), jsvGetInteger(length))",
"params" : [ [ "arr", "JsVar", "The array or typed array to base this off, or an integer which is the array length" ],
[ "byteOffset", "int", "The byte offset in the ArrayBuffer (ONLY IF the first argument was an ArrayBuffer)" ],
[ "length", "int", "The length (ONLY IF the first argument was an ArrayBuffer)" ] ],
"return" : [ "JsVar", "A typed array" ]
}*/
/*JSON{ "type":"constructor", "class": "Uint16Array", "name": "Uint16Array",
"description" : "Create a typed array based on the given input. Either an existing Array Buffer, an Integer as a Length, or a simple array",
"generate_full" : "jswrap_typedarray_constructor(ARRAYBUFFERVIEW_UINT16, arr, jsvGetInteger(byteOffset), jsvGetInteger(length))",
"params" : [ [ "arr", "JsVar", "The array or typed array to base this off, or an integer which is the array length" ],
[ "byteOffset", "int", "The byte offset in the ArrayBuffer (ONLY IF the first argument was an ArrayBuffer)" ],
[ "length", "int", "The length (ONLY IF the first argument was an ArrayBuffer)" ] ],
"return" : [ "JsVar", "A typed array" ]
}*/
/*JSON{ "type":"constructor", "class": "Int16Array", "name": "Int16Array",
"description" : "Create a typed array based on the given input. Either an existing Array Buffer, an Integer as a Length, or a simple array",
"generate_full" : "jswrap_typedarray_constructor(ARRAYBUFFERVIEW_INT16, arr, jsvGetInteger(byteOffset), jsvGetInteger(length))",
"params" : [ [ "arr", "JsVar", "The array or typed array to base this off, or an integer which is the array length" ],
[ "byteOffset", "int", "The byte offset in the ArrayBuffer (ONLY IF the first argument was an ArrayBuffer)" ],
[ "length", "int", "The length (ONLY IF the first argument was an ArrayBuffer)" ] ],
"return" : [ "JsVar", "A typed array" ]
}*/
/*JSON{ "type":"constructor", "class": "Uint32Array", "name": "Uint32Array",
"description" : "Create a typed array based on the given input. Either an existing Array Buffer, an Integer as a Length, or a simple array",
"generate_full" : "jswrap_typedarray_constructor(ARRAYBUFFERVIEW_UINT32, arr, jsvGetInteger(byteOffset), jsvGetInteger(length))",
"params" : [ [ "arr", "JsVar", "The array or typed array to base this off, or an integer which is the array length" ],
[ "byteOffset", "int", "The byte offset in the ArrayBuffer (ONLY IF the first argument was an ArrayBuffer)" ],
[ "length", "int", "The length (ONLY IF the first argument was an ArrayBuffer)" ] ],
"return" : [ "JsVar", "A typed array" ]
}*/
/*JSON{ "type":"constructor", "class": "Int32Array", "name": "Int32Array",
"description" : "Create a typed array based on the given input. Either an existing Array Buffer, an Integer as a Length, or a simple array",
"generate_full" : "jswrap_typedarray_constructor(ARRAYBUFFERVIEW_INT32, arr, jsvGetInteger(byteOffset), jsvGetInteger(length))",
"params" : [ [ "arr", "JsVar", "The array or typed array to base this off, or an integer which is the array length" ],
[ "byteOffset", "int", "The byte offset in the ArrayBuffer (ONLY IF the first argument was an ArrayBuffer)" ],
[ "length", "int", "The length (ONLY IF the first argument was an ArrayBuffer)" ] ],
"return" : [ "JsVar", "A typed array" ]
}*/
/*JSON{ "type":"constructor", "class": "Float32Array", "name": "Float32Array",
"description" : "Create a typed array based on the given input. Either an existing Array Buffer, an Integer as a Length, or a simple array",
"generate_full" : "jswrap_typedarray_constructor(ARRAYBUFFERVIEW_FLOAT32, arr, jsvGetInteger(byteOffset), jsvGetInteger(length))",
"params" : [ [ "arr", "JsVar", "The array or typed array to base this off, or an integer which is the array length" ],
[ "byteOffset", "int", "The byte offset in the ArrayBuffer (ONLY IF the first argument was an ArrayBuffer)" ],
[ "length", "int", "The length (ONLY IF the first argument was an ArrayBuffer)" ] ],
"return" : [ "JsVar", "A typed array" ]
}*/
/*JSON{ "type":"constructor", "class": "Float64Array", "name": "Float64Array",
"description" : "Create a typed array based on the given input. Either an existing Array Buffer, an Integer as a Length, or a simple array",
"generate_full" : "jswrap_typedarray_constructor(ARRAYBUFFERVIEW_FLOAT64, arr, jsvGetInteger(byteOffset), jsvGetInteger(length))",
"params" : [ [ "arr", "JsVar", "The array or typed array to base this off, or an integer which is the array length" ],
[ "byteOffset", "int", "The byte offset in the ArrayBuffer (ONLY IF the first argument was an ArrayBuffer)" ],
[ "length", "int", "The length (ONLY IF the first argument was an ArrayBuffer)" ] ],
"return" : [ "JsVar", "A typed array" ]
}*/
JsVar *jswrap_typedarray_constructor(JsVarDataArrayBufferViewType type, JsVar *arr, JsVarInt byteOffset, JsVarInt length) {
JsVar *arrayBuffer = 0;
if (jsvIsArrayBuffer(arr)) {
arrayBuffer = jsvLockAgain(arr);
} else if (jsvIsInt(arr)) {
length = jsvGetInteger(arr);
byteOffset = 0;
arrayBuffer = jswrap_arraybuffer_constructor(JSV_ARRAYBUFFER_GET_SIZE(type)*length);
} else if (jsvIsArray(arr)) {
length = jsvGetArrayLength(arr);
byteOffset = 0;
arrayBuffer = jswrap_arraybuffer_constructor(JSV_ARRAYBUFFER_GET_SIZE(type)*length);
// later on we'll populate this
}
if (!arrayBuffer) {
jsError("Unsupported first argument\n");
return 0;
}
if (length<=0) length = (JsVarInt)jsvGetArrayBufferLength(arrayBuffer) / JSV_ARRAYBUFFER_GET_SIZE(type);
JsVar *typedArr = jsvNewWithFlags(JSV_ARRAYBUFFER);
if (typedArr) {
typedArr->varData.arraybuffer.type = type;
typedArr->varData.arraybuffer.byteOffset = (unsigned short)byteOffset;
typedArr->varData.arraybuffer.length = (unsigned short)length;
typedArr->firstChild = jsvGetRef(jsvRef(arrayBuffer));
if (jsvIsArray(arr)) {
// if we were given an array, populate this ArrayBuffer
JsArrayIterator it;
jsvArrayIteratorNew(&it, arr);
while (jsvArrayIteratorHasElement(&it)) {
JsVar *idx = jsvArrayIteratorGetIndex(&it);
if (jsvIsInt(idx)) {
JsVar *val = jsvArrayIteratorGetElement(&it);
jsvArrayBufferSet(typedArr, jsvGetInteger(idx), val);
jsvUnLock(val);
}
jsvUnLock(idx);
jsvArrayIteratorNext(&it);
}
jsvArrayIteratorFree(&it);
}
}
jsvUnLock(arrayBuffer);
return typedArr;
}
/*JSON{ "type":"property", "class": "ArrayBufferView", "name": "buffer",
"description" : "The buffer this view references",
"generate_full" : "jsvLock(parent->firstChild)",
"return" : [ "JsVar", "An ArrayBuffer object" ]
}*/
/*JSON{ "type":"property", "class": "ArrayBufferView", "name": "byteLength",
"description" : "The length, in bytes, of the view",
"generate_full" : "parent->varData.arraybuffer.length * JSV_ARRAYBUFFER_GET_SIZE(parent->varData.arraybuffer.type)",
"return" : [ "int", "The Length" ]
}*/
/*JSON{ "type":"property", "class": "ArrayBufferView", "name": "byteOffset",
"description" : "The offset, in bytes, to the first byte of the view within the ArrayBuffer",
"generate_full" : "parent->varData.arraybuffer.byteOffset",
"return" : [ "int", "The byte Offset" ]
}*/
/*JSON{ "type":"method", "class": "ArrayBufferView", "name": "interpolate",
"description" : "Interpolate between two adjacent values in the Typed Array",
"generate" : "jswrap_arraybufferview_interpolate",
"params" : [ [ "index", "float", "Floating point index to access" ] ],
"return" : [ "float", "The result of interpolating between (int)index and (int)(index+1)" ]
}*/
JsVarFloat jswrap_arraybufferview_interpolate(JsVar *parent, JsVarFloat findex) {
int idx = (int)findex;
JsVarFloat a = findex-idx;
JsvArrayBufferIterator it;
jsvArrayBufferIteratorNew(&it, parent, idx);
JsVarFloat fa = jsvArrayBufferIteratorGetFloatValue(&it);
jsvArrayBufferIteratorNext(&it);
JsVarFloat fb = jsvArrayBufferIteratorGetFloatValue(&it);
jsvArrayBufferIteratorFree(&it);
return fa*(1-a) + fb*a;
}
/*JSON{ "type":"method", "class": "ArrayBufferView", "name": "interpolate2d",
"description" : "Interpolate between two adjacent values in the Typed Array",
"generate" : "jswrap_arraybufferview_interpolate2d",
"params" : [ [ "width", "int", "Integer 'width' of 2d array" ],
[ "x", "float", "Floating point X index to access" ],
[ "y", "float", "Floating point Y index to access" ] ],
"return" : [ "float", "The result of interpolating in 2d between the 4 surrounding cells" ]
}*/
JsVarFloat jswrap_arraybufferview_interpolate2d(JsVar *parent, JsVarInt width, JsVarFloat x, JsVarFloat y) {
int yidx = (int)y;
JsVarFloat ay = y-yidx;
JsVarFloat findex = x + (JsVarFloat)(yidx*width);
int idx = (int)findex;
JsVarFloat ax = findex-idx;
JsvArrayBufferIterator it;
jsvArrayBufferIteratorNew(&it, parent, idx);
JsVarFloat xa,xb;
int i;
xa = jsvArrayBufferIteratorGetFloatValue(&it);
jsvArrayBufferIteratorNext(&it);
xb = jsvArrayBufferIteratorGetFloatValue(&it);
JsVarFloat ya = xa*(1-ax) + xb*ax;
for (i=1;i<width;i++) jsvArrayBufferIteratorNext(&it);
xa = jsvArrayBufferIteratorGetFloatValue(&it);
jsvArrayBufferIteratorNext(&it);
xb = jsvArrayBufferIteratorGetFloatValue(&it);
jsvArrayBufferIteratorFree(&it);
JsVarFloat yb = xa*(1-ax) + xb*ax;
return ya*(1-ay) + yb*ay;
}

View File

@@ -0,0 +1,19 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* JavaScript methods and functions in the global namespace
* ----------------------------------------------------------------------------
*/
#include "jsvar.h"
JsVar *jswrap_arraybuffer_constructor(JsVarInt byteLength);
JsVar *jswrap_typedarray_constructor(JsVarDataArrayBufferViewType type, JsVar *arr, JsVarInt byteOffset, JsVarInt length);
JsVarFloat jswrap_arraybufferview_interpolate(JsVar *parent, JsVarFloat index);
JsVarFloat jswrap_arraybufferview_interpolate2d(JsVar *parent, JsVarInt width, JsVarFloat x, JsVarFloat y);

View File

@@ -0,0 +1,102 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* This file is designed to be parsed during the build process
*
* JavaScript methods and functions in the global namespace
* ----------------------------------------------------------------------------
*/
#include "jswrap_functions.h"
#include "jslex.h"
#include "jsparse.h"
#include "jsinteractive.h"
/*JSON{ "type":"variable", "name" : "arguments",
"description" : "A variable containing the arguments given to the function",
"generate" : "jswrap_arguments",
"return" : ["JsVar", "An array containing all the arguments given to the function"]
}*/
extern JsExecInfo execInfo;
JsVar *jswrap_arguments() {
JsVar *scope = 0;
if (execInfo.scopeCount>0)
scope = jsvLock(execInfo.scopes[execInfo.scopeCount-1]);
if (!jsvIsFunction(scope)) {
jsvUnLock(scope);
jsError("Can only use 'arguments' variable inside a function");
return 0;
}
JsVar *args = jsvNewWithFlags(JSV_ARRAY);
if (!args) return 0; // out of memory
JsObjectIterator it;
jsvObjectIteratorNew(&it, scope);
while (jsvObjectIteratorHasElement(&it)) {
JsVar *idx = jsvObjectIteratorGetKey(&it);
if (jsvIsFunctionParameter(idx)) {
JsVar *val = jsvSkipOneName(idx);
jsvArrayPushAndUnLock(args, val);
}
jsvUnLock(idx);
jsvObjectIteratorNext(&it);
}
jsvObjectIteratorFree(&it);
jsvUnLock(scope);
return args;
}
/*JSON{ "type":"function", "name" : "eval",
"description" : "Evaluate a string containing JavaScript code",
"generate" : "jswrap_eval",
"params" : [ [ "code", "JsVar", ""] ],
"return" : ["JsVar", "The result of evaluating the string"]
}*/
JsVar *jswrap_eval(JsVar *v) {
if (!v) return 0;
JsVar *s = jsvAsString(v, false); // get as a string
JsVar *result = jspEvaluateVar(jsiGetParser(), s, 0);
jsvUnLock(s);
return result;
}
/*JSON{ "type":"function", "name" : "parseInt",
"description" : "Convert a string representing a number into an integer",
"generate" : "jswrap_parseInt",
"params" : [ [ "string", "JsVar", ""],
[ "radix", "JsVar", "The Radix of the string (optional)"] ],
"return" : ["JsVar", "The integer value of the string (or NaN)"]
}*/
JsVar *jswrap_parseInt(JsVar *v, JsVar *radixVar) {
int radix = 0/*don't force radix*/;
if (jsvIsNumeric(radixVar))
radix = (int)jsvGetInteger(radixVar);
char buffer[JS_NUMBER_BUFFER_SIZE];
jsvGetString(v, buffer, JS_NUMBER_BUFFER_SIZE);
bool hasError;
JsVarInt i = stringToIntWithRadix(buffer, radix, &hasError);
if (hasError) return jsvNewFromFloat(NAN);
return jsvNewFromInteger(i);
}
/*JSON{ "type":"function", "name" : "parseFloat",
"description" : "Convert a string representing a number into an float",
"generate" : "jswrap_parseFloat",
"params" : [ [ "string", "JsVar", ""] ],
"return" : ["float", "The value of the string"]
}*/
JsVarFloat jswrap_parseFloat(JsVar *v) {
char buffer[JS_NUMBER_BUFFER_SIZE];
jsvGetString(v, buffer, JS_NUMBER_BUFFER_SIZE);
return stringToFloat(buffer);
}

View File

@@ -0,0 +1,19 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* JavaScript methods and functions in the global namespace
* ----------------------------------------------------------------------------
*/
#include "jsvar.h"
JsVar *jswrap_arguments();
JsVar *jswrap_eval(JsVar *v);
JsVar *jswrap_parseInt(JsVar *v, JsVar *radixVar);
JsVarFloat jswrap_parseFloat(JsVar *v);

View File

@@ -0,0 +1,203 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* This file is designed to be parsed during the build process
*
* JavaScript methods and functions for the interactive shell
* ----------------------------------------------------------------------------
*/
#include "jswrap_interactive.h"
#include "jsinteractive.h"
/*JSON{ "type":"function", "name" : "setBusyIndicator",
"description" : "When Espruino is busy, set the pin specified here high. Set this to undefined to disable the feature.",
"generate" : "jswrap_interface_setBusyIndicator",
"params" : [ [ "pin", "JsVar", ""] ]
}*/
void jswrap_interface_setBusyIndicator(JsVar *pinVar) {
Pin oldPin = pinBusyIndicator;
pinBusyIndicator = jshGetPinFromVar(pinVar);
// we should be busy right now anyway, so set stuff up right
if (pinBusyIndicator!=oldPin) {
if (oldPin!=PIN_UNDEFINED) jshPinOutput(oldPin, 0);
if (pinBusyIndicator!=PIN_UNDEFINED) jshPinOutput(pinBusyIndicator, 1);
}
}
/*JSON{ "type":"function", "name" : "setSleepIndicator",
"description" : "When Espruino is asleep, set the pin specified here high. Set this to undefined to disable the feature.",
"generate" : "jswrap_interface_setSleepIndicator",
"params" : [ [ "pin", "JsVar", ""] ]
}*/
void jswrap_interface_setSleepIndicator(JsVar *pinVar) {
pinSleepIndicator = jshGetPinFromVar(pinVar);
}
/*JSON{ "type":"function", "name" : "setDeepSleep",
"description" : [ "Set whether we can enter deep sleep mode, which reduces power consumption to around 1mA. This only works on the Espruino Board.",
"Deep Sleep is currently beta. Espruino will only enter Deep Sleep when there are no timers and it is not connected to USB. USB will not wake Espruino from Deep Sleep, nor will Serial comms (only setWatch will wake it). The System Timer will also pause." ],
"generate" : "jswrap_interface_setDeepSleep",
"params" : [ [ "sleep", "bool", ""] ]
}*/
void jswrap_interface_setDeepSleep(bool sleep) {
allowDeepSleep = sleep;
}
/*JSON{ "type":"function", "name" : "trace", "ifndef" : "SAVE_ON_FLASH",
"description" : "Output debugging information",
"generate" : "jswrap_interface_trace",
"params" : [ [ "root", "JsVarName", "The symbol to output (optional). If nothing is specified, everything will be output"] ]
}*/
void jswrap_interface_trace(JsVar *root) {
if (jsvIsUndefined(root)) {
jsvTrace(jsvGetRef(jsiGetParser()->root), 0);
} else {
jsvTrace(jsvGetRef(root), 0);
}
}
/*XXX{ "type":"function", "name" : "dotty",
"description" : "Output dotty-format graph of debugging information",
"generate_full" : "jsvDottyOutput()"
}*/
/*JSON{ "type":"function", "name" : "dump",
"description" : ["Output current interpreter state in a text form such that it can be copied to a new device",
"Note: 'Internal' functions are currently not handled correctly. You will need to recreate these in the onInit function."],
"generate_full" : "jsiDumpState()"
}*/
/*JSON{ "type":"function", "name" : "load",
"description" : ["Load program memory out of flash",
"This command only executes when the Interpreter returns to the Idle state - for instance ```a=1;load();a=2;``` will still leave 'a' as undefined (or what it was set to in the saved program)."],
"generate_full" : "jsiSetTodo(TODO_FLASH_LOAD)"
}*/
/*JSON{ "type":"function", "name" : "save",
"description" : ["Save program memory into flash. It will then be loaded automatically every time Espruino powers on or is hard-reset.",
"This command only executes when the Interpreter returns to the Idle state - for instance ```a=1;save();a=2;``` will save 'a' as 2.",
"In order to stop the program saved with this command being loaded automatically, hold down Button 1 while also pressing reset. On some boards, Button 1 enters bootloader mode, so you will need to press Reset with Button 1 raised, and then hold Button 1 down a fraction of a second later."],
"generate_full" : "jsiSetTodo(TODO_FLASH_SAVE)"
}*/
/*JSON{ "type":"function", "name" : "reset",
"description" : ["Reset the interpreter - clear program memory, and do not load a saved program from flash. This does NOT reset the underlying hardware (which allows you to reset the device without it disconnecting from USB).",
"This command only executes when the Interpreter returns to the Idle state - for instance ```a=1;reset();a=2;``` will still leave 'a' as undefined.",
"The safest way to do a full reset is to hit the reset button."],
"generate_full" : "jsiSetTodo(TODO_RESET)"
}*/
/*JSON{ "type":"function", "name" : "print",
"description" : "Print the supplied string",
"generate" : "jswrap_interface_print",
"params" : [ [ "text", "JsVarArray", ""] ]
}*/
/*JSON{ "type":"staticmethod", "class":"console", "name" : "log",
"description" : "Print the supplied string(s)",
"generate" : "jswrap_interface_print",
"params" : [ [ "text", "JsVarArray", "One or more arguments to print"] ]
}*/
void jswrap_interface_print(JsVar *v) {
assert(jsvIsArray(v));
JsArrayIterator it;
jsvArrayIteratorNew(&it, v);
while (jsvArrayIteratorHasElement(&it)) {
JsVar *v = jsvAsString(jsvArrayIteratorGetElement(&it), true);
jsiConsoleRemoveInputLine();
jsiConsolePrintStringVar(v);
jsvUnLock(v);
jsvArrayIteratorNext(&it);
if (jsvArrayIteratorHasElement(&it))
jsiConsolePrint(" ");
}
jsvArrayIteratorFree(&it);
jsiConsolePrint("\n");
}
/*JSON{ "type":"function", "name" : "edit",
"description" : ["Fill the console with the contents of the given function, so you can edit it.",
"NOTE: This is a convenience function - it will not edit 'inner functions'. For that, you must edit the 'outer function' and re-execute it."],
"generate" : "jswrap_interface_edit",
"params" : [ [ "funcName", "JsVarName", "The name of the function to edit (either a string or just the unquoted name)"] ]
}*/
void jswrap_interface_edit(JsVar *funcName) {
if (jsvIsString(funcName)) {
JsVar *func = 0;
if (jsvIsName(funcName))
func = jsvSkipName(funcName);
else
func = jsvSkipNameAndUnLock(jsvFindChildFromVar(jsiGetParser()->root, funcName, 0));
if (jsvIsFunction(func)) {
JsVar *scopeVar = jsvFindChildFromString(func, JSPARSE_FUNCTION_SCOPE_NAME, false);
JsVarRef scope = jsvGetRef(scopeVar);
jsvUnLock(scopeVar);
JsVar *newLine = jsvNewFromEmptyString();
if (newLine) { // could be out of memory
jsvAppendStringVarComplete(newLine, funcName);
if (scope) {
// If we have a scope, it's an internal function so we will need to write different code
jsvAppendString(newLine, ".replaceWith(");
} else {
jsvAppendString(newLine, " = ");
}
JsVar *funcData = jsvAsString(func, false);
if (funcData)
jsvAppendStringVarComplete(newLine, funcData);
jsvUnLock(funcData);
if (scope) {
jsvAppendString(newLine, ");");
} else {
jsvAppendString(newLine, ";");
}
jsiReplaceInputLine(newLine);
jsvUnLock(newLine);
}
} else {
jsError("Edit should be called with the name of a function");
}
jsvUnLock(func);
} else {
jsError("Edit should be called with edit(funcName) or edit('funcName')");
}
}
/*JSON{ "type":"function", "name" : "echo",
"description" : "Should TinyJS echo what you type back to you? true = yes (Default), false = no. When echo is off, the result of executing a command is not returned. Instead, you must use 'print' to send output.",
"generate" : "jswrap_interface_echo",
"params" : [ [ "echoOn", "bool", ""] ]
}*/
void jswrap_interface_echo(bool echoOn) {
echo = echoOn;
}
/*JSON{ "type":"function", "name" : "getTime",
"description" : "Return the current system time in Seconds (as a floating point number)",
"generate_full" : "(JsVarFloat)jshGetSystemTime() / (JsVarFloat)jshGetTimeFromMilliseconds(1000)",
"return" : ["float", ""]
}*/
/*JSON{ "type":"function", "name" : "getSerial",
"description" : "Get the serial number of this board",
"generate" : "jswrap_interface_getSerial",
"return" : ["JsVar", "The board's serial number"]
}*/
JsVar *jswrap_interface_getSerial() {
char buf[8];
unsigned char serial[32];
int i, serialSize = jshGetSerialNumber(serial, sizeof(serial));
JsVar *str = jsvNewFromEmptyString();
if (!str) return 0;
for (i=0;i<serialSize;i++) {
if ((i&3)==0 && i) jsvAppendString(str, "-");
itoa(serial[i] | 0x100, buf, 16);
jsvAppendString(str, &buf[1]);
}
return str;
}

View File

@@ -0,0 +1,24 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* JavaScript methods and functions for the interactive shell
* ----------------------------------------------------------------------------
*/
#include "jsvar.h"
#include "jsinteractive.h"
void jswrap_interface_setBusyIndicator(JsVar *pinVar);
void jswrap_interface_setSleepIndicator(JsVar *pinVar);
void jswrap_interface_setDeepSleep(bool sleep);
void jswrap_interface_trace(JsVar *root);
void jswrap_interface_print(JsVar *v);
void jswrap_interface_edit(JsVar *funcName);
void jswrap_interface_echo(bool echoOn);
JsVar *jswrap_interface_getSerial();

View File

@@ -0,0 +1,437 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* This file is designed to be parsed during the build process
*
* JavaScript Hardware IO Functions
* ----------------------------------------------------------------------------
*/
#include "jswrap_io.h"
#include "jsvar.h"
/*JSON{ "type":"function", "name" : "peek8",
"description" : [ "Read 8 bits of memory at the given location - DANGEROUS!" ],
"generate_full" : "(JsVarInt)*(unsigned char*)jsvGetInteger(addr)",
"params" : [ [ "addr", "int", "The address in memory to read"] ],
"return" : ["int", "The value of memory at the given location"]
}*/
/*JSON{ "type":"function", "name" : "poke8",
"description" : [ "Write 8 bits of memory at the given location - VERY DANGEROUS!" ],
"generate_full" : "(*(unsigned char*)jsvGetInteger(addr)) = (unsigned char)jsvGetInteger(value)",
"params" : [ [ "addr", "int", "The address in memory to write"],
[ "value", "int", "The value to write"] ]
}*/
/*JSON{ "type":"function", "name" : "peek16",
"description" : [ "Read 16 bits of memory at the given location - DANGEROUS!" ],
"generate_full" : "(JsVarInt)*(unsigned short*)jsvGetInteger(addr)",
"params" : [ [ "addr", "int", "The address in memory to read"] ],
"return" : ["int", "The value of memory at the given location"]
}*/
/*JSON{ "type":"function", "name" : "poke16",
"description" : [ "Write 16 bits of memory at the given location - VERY DANGEROUS!" ],
"generate_full" : "(*(unsigned short*)jsvGetInteger(addr)) = (unsigned short)jsvGetInteger(value)",
"params" : [ [ "addr", "int", "The address in memory to write"],
[ "value", "int", "The value to write"] ]
}*/
/*JSON{ "type":"function", "name" : "peek32",
"description" : [ "Read 32 bits of memory at the given location - DANGEROUS!" ],
"generate_full" : "(JsVarInt)*(unsigned int*)jsvGetInteger(addr)",
"params" : [ [ "addr", "int", "The address in memory to read"] ],
"return" : ["int", "The value of memory at the given location"]
}*/
/*JSON{ "type":"function", "name" : "poke32",
"description" : [ "Write 32 bits of memory at the given location - VERY DANGEROUS!" ],
"generate_full" : "(*(unsigned int*)jsvGetInteger(addr)) = (unsigned int)jsvGetInteger(value)",
"params" : [ [ "addr", "int", "The address in memory to write"],
[ "value", "int", "The value to write"] ]
}*/
/*JSON{ "type":"function", "name" : "analogRead",
"description" : ["Get the analog value of the given pin",
"This is different to Arduino which only returns an integer between 0 and 1023",
"However only pins connected to an ADC will work (see the datasheet)"],
"generate" : "jshPinAnalog",
"params" : [ [ "pin", "pin", "The pin to use"] ],
"return" : ["float", "The analog Value of the Pin between 0 and 1"]
}*/
/*JSON{ "type":"function", "name" : "analogWrite",
"description" : "Set the analog Value of a pin. It will be output using PWM",
"generate" : "jswrap_io_analogWrite",
"params" : [ [ "pin", "pin", "The pin to use"],
[ "value", "float", "A value between 0 and 1"],
[ "options", "JsVar", ["An object containing options.",
"Currently only freq (pulse frequency in Hz) is available: ```analogWrite(LED1,0.5,{ freq : 10 });``` ",
"Note that specifying a frequency will force PWM output, even if the pin has a DAC"] ] ]
}*/
void jswrap_io_analogWrite(Pin pin, JsVarFloat value, JsVar *options) {
JsVarFloat freq = 0;
if (jsvIsObject(options)) {
freq = jsvGetFloatAndUnLock(jsvObjectGetChild(options, "freq", 0));
}
jshPinAnalogOutput(pin, value, freq);
}
/*JSON{ "type":"function", "name" : "digitalPulse",
"description" : ["Pulse the pin with the value for the given time in milliseconds",
"eg. ```pulse(A0,1,5);``` pulses A0 high for 5ms",
"digitalPulse is for SHORT pulses that need to be very accurate. If you're doing anything over a few milliseconds, use setTimeout instead" ],
"generate" : "jswrap_io_digitalPulse",
"params" : [ [ "pin", "pin", "The pin to use"],
[ "value", "bool", "Whether to pulse high (true) or low (false)"],
[ "time", "float", "A time in milliseconds"] ]
}*/
void jswrap_io_digitalPulse(Pin pin, bool value, JsVarFloat time) {
if (time<=0) {
jsWarn("Pulse Time given for digitalPulse is less that or equal to 0");
} else {
//jsPrintInt((JsVarInt)(time*1000));
jshPinPulse(pin, value, time);
}
}
/*JSON{ "type":"function", "name" : "digitalWrite",
"description" : ["Set the digital value of the given pin",
"If pin is an array of pins, eg. ```[A2,A1,A0]``` the value will be treated as an integer where the first array element is the MSB" ],
"generate" : "jswrap_io_digitalWrite",
"params" : [ [ "pin", "JsVar", "The pin to use"],
[ "value", "int", "Whether to pulse high (true) or low (false)"] ]
}*/
void jswrap_io_digitalWrite(JsVar *pinVar, JsVarInt value) {
if (jsvIsArray(pinVar)) {
JsVarRef pinName = pinVar->lastChild; // NOTE: start at end and work back!
while (pinName) {
JsVar *pinNamePtr = jsvLock(pinName);
JsVar *pinPtr = jsvSkipName(pinNamePtr);
jshPinOutput(jshGetPinFromVar(pinPtr), value&1);
jsvUnLock(pinPtr);
pinName = pinNamePtr->prevSibling;
jsvUnLock(pinNamePtr);
value = value>>1; // next bit down
}
} else {
Pin pin = jshGetPinFromVar(pinVar);
jshPinOutput(pin, value!=0);
}
}
/*JSON{ "type":"function", "name" : "digitalRead",
"description" : ["Get the digital value of the given pin",
"If pin is an array of pins, eg. ```[A2,A1,A0]``` the value will be treated as an integer where the first array element is the MSB" ],
"generate" : "jswrap_io_digitalRead",
"params" : [ [ "pin", "JsVar", "The pin to use"] ],
"return" : ["int", "The digital Value of the Pin"]
}*/
JsVarInt jswrap_io_digitalRead(JsVar *pinVar) {
if (jsvIsArray(pinVar)) {
int pins = 0;
JsVarInt value = 0;
JsVarRef pinName = pinVar->firstChild;
while (pinName) {
JsVar *pinNamePtr = jsvLock(pinName);
JsVar *pinPtr = jsvSkipName(pinNamePtr);
value = (value<<1) | jshPinInput(jshGetPinFromVar(pinPtr));
jsvUnLock(pinPtr);
pinName = pinNamePtr->nextSibling;
jsvUnLock(pinNamePtr);
pins++;
}
if (pins==0) return 0; // return undefined if array empty
return value;
} else {
Pin pin = jshGetPinFromVar(pinVar);
return jshPinInput(pin);
}
}
/*JSON{ "type":"function", "name" : "pinMode",
"description" : ["Set the mode of the given pin - note that digitalRead/digitalWrite/etc set this automatically unless pinMode has been called first. If you want digitalRead/etc to set the pin mode automatically after you have called pinMode, simply call it again with no mode argument: ```pinMode(pin)```" ],
"generate" : "jswrap_io_pinMode",
"params" : [ [ "pin", "pin", "The pin to use"], [ "mode", "JsVar", "The mode - a string that is either 'input', 'output', 'input_pullup', or 'input_pulldown'. Do not include this argument if you want to revert to automatic pin mode setting."] ]
}*/
void jswrap_io_pinMode(Pin pin, JsVar *mode) {
if (!jshIsPinValid(pin)) {
jsError("Invalid pin");
return;
}
JshPinState m = JSHPINSTATE_UNDEFINED;
if (jsvIsString(mode)) {
if (jsvIsStringEqual(mode, "input")) m = JSHPINSTATE_GPIO_IN;
if (jsvIsStringEqual(mode, "input_pullup")) m = JSHPINSTATE_GPIO_IN_PULLUP;
if (jsvIsStringEqual(mode, "input_pulldown")) m = JSHPINSTATE_GPIO_IN_PULLDOWN;
if (jsvIsStringEqual(mode, "output")) m = JSHPINSTATE_GPIO_OUT;
}
if (m != JSHPINSTATE_UNDEFINED) {
jshSetPinStateIsManual(pin, true);
jshPinSetState(pin, m);
} else {
jshSetPinStateIsManual(pin, false);
if (!jsvIsUndefined(mode)) {
jsError("Unknown pin mode");
}
}
}
/*XXXX{ "type":"function", "name" : "bitBang",
"description" : ["bitBang out a message in a one-wire style BROKEN CURRENTLY" ],
"generate" : "jshBitBang",
"params" : [ [ "pin", "pin", "The pin to use"],
[ "t0h", "float", "The time (in milliseconds) to spend high for a 0"],
[ "t0l", "float", "The time (in milliseconds) to spend low for a 0"],
[ "t1h", "float", "The time (in milliseconds) to spend high for a 1"],
[ "t1l", "float", "The time (in milliseconds) to spend low for a 1"],
[ "data", "JsVar", "A string representing the data"] ]
}*/
/*JSON{ "type":"function", "name" : "setInterval",
"description" : ["Call the function specified REPEATEDLY after the timeout in milliseconds.",
"The function that is being called may also take an argument, which is an object containing a field called 'time' (the time in seconds at which the timer happened)",
"for example: ```setInterval(function (e) { print(e.time); }, 1000);```",
"This can also be removed using clearInterval" ],
"generate" : "jswrap_interface_setInterval",
"params" : [ [ "function", "JsVarName", "A Function or String to be executed"],
[ "timeout", "float", "The time between calls to the function" ] ],
"return" : ["JsVar", "An ID that can be passed to clearInterval"]
}*/
/*JSON{ "type":"function", "name" : "setTimeout",
"description" : ["Call the function specified ONCE after the timeout in milliseconds.",
"The function that is being called may also take an argument, which is an object containing a field called 'time' (the time in seconds at which the timer happened)",
"for example: ```setTimeout(function (e) { print(e.time); }, 1000);```",
"This can also be removed using clearTimeout" ],
"generate" : "jswrap_interface_setTimeout",
"params" : [ [ "function", "JsVarName", "A Function or String to be executed"],
[ "timeout", "float", "The time until the function will be executed" ] ],
"return" : ["JsVar", "An ID that can be passed to clearTimeout"]
}*/
JsVar *_jswrap_interface_setTimeoutOrInterval(JsVar *func, JsVarFloat interval, bool isTimeout) {
JsVar *skippedFunc = jsvSkipName(func);
JsVar *itemIndex = 0;
if (!jsvIsFunction(skippedFunc) && !jsvIsString(skippedFunc)) {
jsError("Function or String not supplied!");
} else {
// Create a new timer
JsVar *timerPtr = jsvNewWithFlags(JSV_OBJECT);
if (interval<TIMER_MIN_INTERVAL) interval=TIMER_MIN_INTERVAL;
JsVar *v;
v = jsvNewFromInteger(jshGetSystemTime() + jshGetTimeFromMilliseconds(interval));
jsvUnLock(jsvAddNamedChild(timerPtr, v, "time"));
jsvUnLock(v);
v = jsvNewFromFloat(interval);
jsvUnLock(jsvAddNamedChild(timerPtr, v, "interval"));
jsvUnLock(v);
v = jsvNewFromBool(!isTimeout);
jsvUnLock(jsvAddNamedChild(timerPtr, v, "recur"));
jsvUnLock(v);
jsvUnLock(jsvAddNamedChild(timerPtr, func, "callback"));
//jsPrint("TIMER BEFORE ADD\n"); jsvTrace(timerArray,5);
JsVar *timerArrayPtr = jsvLock(timerArray);
itemIndex = jsvNewFromInteger(jsvArrayPushWithInitialSize(timerArrayPtr, timerPtr, 1) - 1);
//jsPrint("TIMER AFTER ADD\n"); jsvTrace(timerArray,5);
jsvUnLock(timerArrayPtr);
jsvUnLock(timerPtr);
}
jsvUnLock(skippedFunc);
//jsvTrace(jsiGetParser()->root, 0);
return itemIndex;
}
JsVar *jswrap_interface_setInterval(JsVar *func, JsVarFloat timeout) {
return _jswrap_interface_setTimeoutOrInterval(func, timeout, false);
}
JsVar *jswrap_interface_setTimeout(JsVar *func, JsVarFloat timeout) {
return _jswrap_interface_setTimeoutOrInterval(func, timeout, true);
}
/*JSON{ "type":"function", "name" : "setWatch",
"description" : ["Call the function specified when the pin changes",
"The function may also take an argument, which is an object containing a field called 'time', which is the time in seconds at which the pin changed state, and 'state', which is the current state of the pin",
" This can also be removed using clearWatch" ],
"generate" : "jswrap_interface_setWatch",
"params" : [ [ "function", "JsVarName", "A Function or String to be executed"],
[ "pin", "pin", "The pin to watch" ],
[ "options", "JsVar", ["If this is a boolean or integer, it determines whether to call this once (false = default) or every time a change occurs (true)",
"If this is an object, it can contain the following information: ```{ repeat: true/false(default), edge:'rising'/'falling'/'both'(default)}```" ] ] ],
"return" : ["JsVar", "An ID that can be passed to clearWatch"]
}*/
JsVar *jswrap_interface_setWatch(JsVar *funcVar, Pin pin, JsVar *repeatOrObject) {
bool repeat = false;
int edge = 0;
if (jsvIsObject(repeatOrObject)) {
JsVar *v;
repeat = jsvGetBoolAndUnLock(jsvObjectGetChild(repeatOrObject, "repeat", 0));
v = jsvObjectGetChild(repeatOrObject, "edge", 0);
if (jsvIsString(v)) {
if (jsvIsStringEqual(v, "rising")) edge=1;
else if (jsvIsStringEqual(v, "falling")) edge=-1;
else if (jsvIsStringEqual(v, "both")) edge=0;
else jsWarn("'edge' in setWatch should be a string - either 'rising', 'falling' or 'both'");
} else if (!jsvIsUndefined(v))
jsWarn("'edge' in setWatch should be a string - either 'rising', 'falling' or 'both'");
jsvUnLock(v);
} else
repeat = jsvGetBool(repeatOrObject);
JsVarInt itemIndex = -1;
JsVar *skippedFunc = jsvSkipName(funcVar);
if (!jsvIsFunction(skippedFunc) && !jsvIsString(skippedFunc)) {
jsError("Function or String not supplied!");
} else {
// Create a new watch
JsVar *watchPtr = jsvNewWithFlags(JSV_OBJECT);
JsVar *v;
v = jsvNewFromPin(pin);
jsvUnLock(jsvAddNamedChild(watchPtr, v, "pin"));
jsvUnLock(v);
v = jsvNewFromBool(repeat);
jsvUnLock(jsvAddNamedChild(watchPtr, v, "recur"));
jsvUnLock(v);
v = jsvNewFromInteger(edge);
jsvUnLock(jsvAddNamedChild(watchPtr, v, "edge"));
jsvUnLock(v);
jsvUnLock(jsvAddNamedChild(watchPtr, funcVar, "callback"));
JsVar *watchArrayPtr = jsvLock(watchArray);
itemIndex = jsvArrayPushWithInitialSize(watchArrayPtr, watchPtr, 1) - 1;
jsvUnLock(watchArrayPtr);
jsvUnLock(watchPtr);
jshPinWatch(pin, true);
}
jsvUnLock(skippedFunc);
return (itemIndex>=0) ? jsvNewFromInteger(itemIndex) : 0/*undefined*/;
}
/*JSON{ "type":"function", "name" : "clearInterval",
"description" : ["Clear the Interval that was created with setInterval, for example:",
"```var id = setInterval(function () { print('foo'); }, 1000);```",
"```clearInterval(id);```",
"If no argument is supplied, all timers and intervals are stopped" ],
"generate" : "jswrap_interface_clearInterval",
"params" : [ [ "id", "JsVar", "The id returned by a previous call to setInterval"] ]
}*/
/*JSON{ "type":"function", "name" : "clearTimeout",
"description" : ["Clear the Timeout that was created with setTimeout, for example:",
"```var id = setTimeout(function () { print('foo'); }, 1000);```",
"```clearTimeout(id);```",
"If no argument is supplied, all timers and intervals are stopped" ],
"generate" : "jswrap_interface_clearTimeout",
"params" : [ [ "id", "JsVar", "The id returned by a previous call to setTimeout"] ]
}*/
void _jswrap_interface_clearTimeoutOrInterval(JsVar *idVar, bool isTimeout) {
if (jsvIsUndefined(idVar)) {
JsVar *timerArrayPtr = jsvLock(timerArray);
jsvRemoveAllChildren(timerArrayPtr);
jsvUnLock(timerArrayPtr);
} else {
JsVar *child = jsvIsBasic(idVar) ? jsvFindChildFromVarRef(timerArray, idVar, false) : 0;
if (child) {
JsVar *timerArrayPtr = jsvLock(timerArray);
jsvRemoveChild(timerArrayPtr, child);
jsvUnLock(child);
jsvUnLock(timerArrayPtr);
} else {
jsError(isTimeout ? "Unknown Timeout" : "Unknown Interval");
}
}
}
void jswrap_interface_clearInterval(JsVar *idVar) {
_jswrap_interface_clearTimeoutOrInterval(idVar, false);
}
void jswrap_interface_clearTimeout(JsVar *idVar) {
_jswrap_interface_clearTimeoutOrInterval(idVar, true);
}
/*JSON{ "type":"function", "name" : "changeInterval",
"description" : ["Change the Interval on a callback created with setInterval, for example:",
"```var id = setInterval(function () { print('foo'); }, 1000); // every second```",
"```changeInterval(id, 1500); // now runs every 1.5 seconds```",
"This takes effect the text time the callback is called (so it is not immediate)."],
"generate" : "jswrap_interface_changeInterval",
"params" : [ [ "id", "JsVar", "The id returned by a previous call to setInterval"],
[ "time","float","The new time period in ms" ] ]
}*/
void jswrap_interface_changeInterval(JsVar *idVar, JsVarFloat interval) {
if (interval<TIMER_MIN_INTERVAL) interval=TIMER_MIN_INTERVAL;
JsVar *timerName = jsvIsBasic(idVar) ? jsvFindChildFromVarRef(timerArray, idVar, false) : 0;
if (timerName) {
JsVar *timer = jsvSkipNameAndUnLock(timerName);
JsVar *v;
v = jsvNewFromFloat(interval);
jsvUnLock(jsvSetNamedChild(timer, v, "interval"));
jsvUnLock(v);
v = jsvNewFromInteger(jshGetSystemTime() + jshGetTimeFromMilliseconds(interval));
jsvUnLock(jsvSetNamedChild(timer, v, "time"));
jsvUnLock(v);
jsvUnLock(timer);
// timerName already unlocked
} else {
jsError("Unknown Interval");
}
}
/*JSON{ "type":"function", "name" : "clearWatch",
"description" : [ "Clear the Watch that was created with setWatch. If no parameter is supplied, all watches will be removed." ],
"generate" : "jswrap_interface_clearWatch",
"params" : [ [ "id", "JsVar", "The id returned by a previous call to setWatch"] ]
}*/
void jswrap_interface_clearWatch(JsVar *idVar) {
if (jsvIsUndefined(idVar)) {
JsVar *watchArrayPtr = jsvLock(watchArray);
// unwatch all pins
JsVarRef watch = watchArrayPtr->firstChild;
while (watch) {
JsVar *watchNamePtr = jsvLock(watch); // effectively the array index
JsVar *pinVar = jsvSkipNameAndUnLock(jsvFindChildFromStringRef(watchNamePtr->firstChild, "pin", false));
jshPinWatch(jshGetPinFromVar(pinVar), false); // 'unwatch' pin because we know that we're removing ALL watches
jsvUnLock(pinVar);
watch = watchNamePtr->nextSibling;
jsvUnLock(watchNamePtr);
}
// remove all items
jsvRemoveAllChildren(watchArrayPtr);
jsvUnLock(watchArrayPtr);
} else {
JsVar *watchNamePtr = jsvFindChildFromVarRef(watchArray, idVar, false);
if (watchNamePtr) { // child is a 'name'
JsVar *pinVar = jsvSkipNameAndUnLock(jsvFindChildFromStringRef(watchNamePtr->firstChild, "pin", false));
Pin pin = jshGetPinFromVar(pinVar);
jsvUnLock(pinVar);
JsVar *watchArrayPtr = jsvLock(watchArray);
jsvRemoveChild(watchArrayPtr, watchNamePtr);
jsvUnLock(watchNamePtr);
// Now check if this pin is still being watched
bool stillWatched = false;
JsArrayIterator it;
jsvArrayIteratorNew(&it, watchArrayPtr);
while (jsvArrayIteratorHasElement(&it)) {
JsVar *watchPtr = jsvArrayIteratorGetElement(&it);
JsVar *pinVar = jsvObjectGetChild(watchPtr, "pin", 0);
if (jshGetPinFromVar(pinVar) == pin)
stillWatched = true;
jsvUnLock(pinVar);
jsvUnLock(watchPtr);
jsvArrayIteratorNext(&it);
}
jsvArrayIteratorFree(&it);
jsvUnLock(watchArrayPtr);
if (!stillWatched)
jshPinWatch(pin, false); // 'unwatch' pin
} else {
jsError("Unknown Watch");
}
}
}

View File

@@ -0,0 +1,29 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* JavaScript Hardware IO Functions
* ----------------------------------------------------------------------------
*/
#include "jsvar.h"
#include "jsinteractive.h"
void jswrap_io_analogWrite(Pin pin, JsVarFloat value, JsVar *options);
void jswrap_io_digitalPulse(Pin pin, bool value, JsVarFloat time);
void jswrap_io_digitalWrite(JsVar *pinVar, JsVarInt value);
JsVarInt jswrap_io_digitalRead(JsVar *pinVar);
void jswrap_io_pinMode(Pin pin, JsVar *mode);
JsVar *jswrap_interface_setInterval(JsVar *func, JsVarFloat timeout);
JsVar *jswrap_interface_setTimeout(JsVar *func, JsVarFloat timeout);
JsVar *jswrap_interface_setWatch(JsVar *funcVar, Pin pin, JsVar *repeatOrObject);
void jswrap_interface_clearInterval(JsVar *idVar);
void jswrap_interface_clearTimeout(JsVar *idVar);
void jswrap_interface_changeInterval(JsVar *idVar, JsVarFloat interval);
void jswrap_interface_clearWatch(JsVar *idVar);

View File

@@ -0,0 +1,167 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* This file is designed to be parsed during the build process
*
* JavaScript JSON-handling Functions
* ----------------------------------------------------------------------------
*/
#include "jswrap_json.h"
#include "jsparse.h"
#include "jsinteractive.h"
#include "jswrapper.h"
/*JSON{ "type":"staticmethod",
"class" : "JSON", "name" : "stringify",
"description" : "Convert the given object into a JSON string which can subsequently be parsed with JSON.parse or eval",
"generate" : "jswrap_json_stringify",
"params" : [ [ "data", "JsVar", "The data to be converted to a JSON string"] ],
"return" : ["JsVar", "A JSON string"]
}*/
JsVar *jswrap_json_stringify(JsVar *v) {
JsVar *result = jsvNewFromEmptyString();
if (result) // could be out of memory
jsfGetJSON(v, result);
return result;
}
/*JSON{ "type":"staticmethod",
"class" : "JSON", "name" : "parse",
"description" : "Parse the given JSON string into a JavaScript object",
"generate" : "jswrap_json_parse",
"params" : [ [ "string", "JsVar", "A JSON string"] ],
"return" : ["JsVar", "The JavaScript object created by parsing the data string"]
}*/
JsVar *jswrap_json_parse(JsVar *v) {
JsVar *res = 0;
JsVar *bracketed = jsvNewFromString("(");
if (bracketed) { // could be out of memory
v = jsvAsString(v, true); // try and get this as a string
jsvAppendStringVarComplete(bracketed, v);
jsvAppendString(bracketed, ")");
res = jspEvaluateVar(jsiGetParser(), bracketed, 0);
jsvUnLock(bracketed);
}
return res;
}
/* This is like jsfGetJSONWithCallback, but handles ONLY functions (and does not print the initial 'function' text) */
void jsfGetJSONForFunctionWithCallback(JsVar *var, JsfGetJSONCallbackString callbackString, JsfGetJSONCallbackVar callbackVar, void *callbackData) {
assert(jsvIsFunction(var));
JsVarRef coderef = 0; // TODO: this should really be in jsvAsString
JsVarRef childref = var->firstChild;
bool firstParm = true;
callbackString(callbackData, "(");
while (childref) {
JsVar *child = jsvLock(childref);
childref = child->nextSibling;
if (jsvIsFunctionParameter(child)) {
if (firstParm)
firstParm=false;
else
callbackString(callbackData, ",");
callbackVar(callbackData, child); // FIXME: escape the string
} else if (jsvIsString(child) && jsvIsStringEqual(child, JSPARSE_FUNCTION_CODE_NAME)) {
coderef = child->firstChild;
}
jsvUnLock(child);
}
callbackString(callbackData, ") ");
if (coderef) {
JsVar *codeVar = jsvLock(coderef);
callbackVar(callbackData, codeVar);
jsvUnLock(codeVar);
} else callbackString(callbackData, "{}");
}
void jsfGetJSONWithCallback(JsVar *var, JsfGetJSONCallbackString callbackString, JsfGetJSONCallbackVar callbackVar, void *callbackData) {
if (jsvIsUndefined(var)) {
callbackString(callbackData, "undefined");
} else if (jsvIsArray(var)) {
int length = (int)jsvGetArrayLength(var);
int i;
callbackString(callbackData, "[");
for (i=0;i<length;i++) {
JsVar *item = jsvGetArrayItem(var, i);
jsfGetJSONWithCallback(item, callbackString, callbackVar, callbackData);
jsvUnLock(item);
if (i<length-1) callbackString(callbackData, ",");
}
callbackString(callbackData, "]");
} else if (jsvIsArrayBuffer(var)) {
callbackString(callbackData, "new ");
callbackString(callbackData, jswGetBasicObjectName(var));
callbackString(callbackData, "([");
callbackVar(callbackData, jsvAsString(var, false));
callbackString(callbackData, "])");
} else if (jsvIsObject(var)) {
bool first = true;
JsVarRef childref = var->firstChild;
callbackString(callbackData, "{");
while (childref) {
JsVar *child = jsvLock(childref);
bool hidden = jsvIsInternalObjectKey(child);
if (!hidden) {
if (first)
first = false;
else
callbackString(callbackData, ",");
callbackString(callbackData, "\"");
callbackVar(callbackData, child); // FIXME: escape the string
callbackString(callbackData, "\":");
}
JsVar *childVar = child->firstChild ? jsvLock(child->firstChild) : 0;
childref = child->nextSibling;
jsvUnLock(child);
if (!hidden) {
jsfGetJSONWithCallback(childVar, callbackString, callbackVar, callbackData);
}
jsvUnLock(childVar);
}
callbackString(callbackData, "}");
} else if (jsvIsFunction(var)) {
callbackString(callbackData, "function ");
jsfGetJSONForFunctionWithCallback(var, callbackString, callbackVar, callbackData);
} else if (jsvIsString(var) && !jsvIsName(var)) {
// escape the string
callbackString(callbackData, "\"");
JsvStringIterator it;
jsvStringIteratorNew(&it, var, 0);
while (jsvStringIteratorHasChar(&it)) {
char ch = jsvStringIteratorGetChar(&it);
callbackString(callbackData, escapeCharacter(ch));
jsvStringIteratorNext(&it);
}
jsvStringIteratorFree(&it);
callbackString(callbackData, "\"");
} else {
JsVar *str = jsvAsString(var, false);
if (str) {
callbackVar(callbackData, str);
jsvUnLock(str);
}
}
}
void jsfGetJSON(JsVar *var, JsVar *result) {
assert(jsvIsString(result));
jsfGetJSONWithCallback(var, (JsfGetJSONCallbackString)jsvAppendString, (JsfGetJSONCallbackVar)jsvAppendStringVarComplete, result);
}
void _jsfPrintJSON_str(void *data, const char *str) { NOT_USED(data); jsiConsolePrint(str); }
void _jsfPrintJSON_var(void *data, JsVar *var) { NOT_USED(data); jsiConsolePrintStringVar(var); }
void jsfPrintJSON(JsVar *var) {
jsfGetJSONWithCallback(var, _jsfPrintJSON_str, _jsfPrintJSON_var, 0);
}
void jsfPrintJSONForFunction(JsVar *var) {
jsfGetJSONForFunctionWithCallback(var, _jsfPrintJSON_str, _jsfPrintJSON_var, 0);
}

View File

@@ -0,0 +1,33 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* JavaScript JSON-handling Functions
* ----------------------------------------------------------------------------
*/
#include "jsvar.h"
JsVar *jswrap_json_stringify(JsVar *v);
JsVar *jswrap_json_parse(JsVar *v);
typedef void (*JsfGetJSONCallbackString)(void *data, const char *string);
typedef void (*JsfGetJSONCallbackVar)(void *data, JsVar *var);
/* This is like jsfGetJSONWithCallback, but handles ONLY functions (and does not print the initial 'function' text) */
void jsfGetJSONForFunctionWithCallback(JsVar *var, JsfGetJSONCallbackString callbackString, JsfGetJSONCallbackVar callbackVar, void *callbackData);
/* Dump to JSON, using the given callbacks for printing data */
void jsfGetJSONWithCallback(JsVar *var, JsfGetJSONCallbackString callbackString, JsfGetJSONCallbackVar callbackVar, void *callbackData);
/* Convenience function for using jsfGetJSONWithCallback - print to var */
void jsfGetJSON(JsVar *var, JsVar *result);
/* Convenience function for using jsfGetJSONWithCallback - print to console */
void jsfPrintJSON(JsVar *var);
/* Convenience function for using jsfGetJSONForFunctionWithCallback - print to console */
void jsfPrintJSONForFunction(JsVar *var);

View File

@@ -0,0 +1,195 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* This file is designed to be parsed during the build process
*
* JavaScript Functions for handling Modules
* ----------------------------------------------------------------------------
*/
#include "jswrap_functions.h"
#include "jslex.h"
#include "jsvar.h"
#include "jsparse.h"
#include "jsinteractive.h"
#include "jswrapper.h"
#ifdef USE_FILESYSTEM
#include "../libs/jswrap_fat.h"
#endif
static JsVar *jswrap_modules_getModuleList() {
JsVar *moduleListName = jsvFindChildFromString(jsiGetParser()->root, JSPARSE_MODULE_CACHE_NAME, true);
if (!moduleListName) return 0; // out of memory
JsVar *moduleList = jsvSkipName(moduleListName);
if (!moduleList) {
moduleList = jsvNewWithFlags(JSV_OBJECT);
if (!moduleList) { jsvUnLock(moduleListName); return 0; } // out of memory
jsvSetValueOfName(moduleListName, moduleList); // no need to unlock
}
jsvUnLock(moduleListName);
return moduleList;
}
/*JSON{ "type":"function", "name" : "require",
"description" : "Load the given module, and return the exported functions",
"generate" : "jswrap_require",
"params" : [ [ "moduleName", "JsVar", "A String containing the name of the given module"] ],
"return" : ["JsVar", "The result of evaluating the string"]
}*/
JsVar *jswrap_require(JsVar *moduleName) {
if (!jsvIsString(moduleName)) {
jsWarn("Expecting a module name as a string, but got %t", moduleName);
return 0;
}
// Search to see if we have already loaded this module
JsVar *moduleList = jswrap_modules_getModuleList();
if (!moduleList) return 0; // out of memory
JsVar *moduleExportName = jsvFindChildFromVar(moduleList, moduleName, true);
jsvUnLock(moduleList);
if (!moduleExportName) return 0; // out of memory
JsVar *moduleExport = jsvSkipName(moduleExportName);
if (moduleExport) {
// Found the module!
jsvUnLock(moduleExportName);
return moduleExport;
}
// Now check if it is built-in
char moduleNameBuf[32];
jsvGetString(moduleName, moduleNameBuf, sizeof(moduleNameBuf));
if (jswIsBuiltInLibrary(moduleNameBuf)) {
// create a 'fake' module that Espruino can use to map its built-in functions against
moduleExport = jspNewBuiltin(moduleNameBuf);
} else {
// Now try and load it
JsVar *fileContents = 0;
//if (jsvIsStringEqual(moduleName,"http")) {}
//if (jsvIsStringEqual(moduleName,"fs")) {}
#ifdef USE_FILESYSTEM
JsVar *modulePath = jsvNewFromString(
#ifdef LINUX
"node_modules/"
#else
"NODE_M~1/"
#endif
);
if (!modulePath) { jsvUnLock(moduleExportName); return 0; } // out of memory
jsvAppendStringVarComplete(modulePath, moduleName);
jsvAppendString(modulePath,".js");
fileContents = wrap_fat_readFile(modulePath);
jsvUnLock(modulePath);
#endif
if (!fileContents || jsvIsStringEqual(fileContents,"")) {
jsvUnLock(moduleExportName);
jsvUnLock(fileContents);
jsWarn("Module not found");
return 0;
}
moduleExport = jspEvaluateModule(jsiGetParser(), fileContents);
jsvUnLock(fileContents);
}
assert(moduleExport);
jsvSetValueOfName(moduleExportName, moduleExport); // save in cache
jsvUnLock(moduleExportName);
return moduleExport;
}
/*JSON{ "type":"staticmethod",
"class" : "Modules", "name" : "getCached",
"description" : "Return an array of module names that have been cached",
"generate" : "jswrap_modules_getCached",
"return" : ["JsVar", "An array of module names"]
}*/
JsVar *jswrap_modules_getCached() {
JsVar *arr = jsvNewWithFlags(JSV_ARRAY);
if (!arr) return 0; // out of memory
JsVar *moduleList = jswrap_modules_getModuleList();
if (!moduleList) return arr; // out of memory
JsObjectIterator it;
jsvObjectIteratorNew(&it, moduleList);
while (jsvObjectIteratorHasElement(&it)) {
JsVar *idx = jsvObjectIteratorGetKey(&it);
JsVar *idxCopy = jsvCopyNameOnly(idx, false, false);
jsvArrayPushAndUnLock(arr, idxCopy);
jsvUnLock(idx);
jsvObjectIteratorNext(&it);
}
jsvObjectIteratorFree(&it);
jsvUnLock(moduleList);
return arr;
}
/*JSON{ "type":"staticmethod",
"class" : "Modules", "name" : "removeCached",
"description" : "Remove the given module from the list of cached modules",
"generate" : "jswrap_modules_removeCached",
"params" : [ [ "id", "JsVar", "The module name to remove"] ]
}*/
void jswrap_modules_removeCached(JsVar *id) {
if (!jsvIsString(id)) {
jsError("The argument to removeCached must be a string");
return;
}
JsVar *moduleList = jswrap_modules_getModuleList();
if (!moduleList) return; // out of memory
JsVar *moduleExportName = jsvFindChildFromVar(moduleList, id, false);
if (!moduleExportName) {
jsWarn("Module not found");
} else {
jsvRemoveChild(moduleList, moduleExportName);
jsvUnLock(moduleExportName);
}
jsvUnLock(moduleList);
}
/*JSON{ "type":"staticmethod",
"class" : "Modules", "name" : "removeAllCached",
"description" : "Remove all cached modules",
"generate" : "jswrap_modules_removeAllCached"
}*/
void jswrap_modules_removeAllCached() {
JsVar *moduleList = jswrap_modules_getModuleList();
if (!moduleList) return; // out of memory
jsvRemoveAllChildren(moduleList);
jsvUnLock(moduleList);
}
/*JSON{ "type":"staticmethod",
"class" : "Modules", "name" : "addCached",
"description" : "Add the given module to the cache",
"generate" : "jswrap_modules_addCached",
"params" : [ [ "id", "JsVar", "The module name to add" ],
[ "sourcecode", "JsVar", "The module's sourcecode" ] ]
}*/
void jswrap_modules_addCached(JsVar *id, JsVar *sourceCode) {
if (!jsvIsString(id) || !jsvIsString(sourceCode)) {
jsError("Both arguments to addCached must be strings");
return;
}
JsVar *moduleList = jswrap_modules_getModuleList();
if (!moduleList) return; // out of memory
JsVar *moduleExport = jspEvaluateModule(jsiGetParser(), sourceCode);
if (!moduleExport) {
jsWarn("Unable to load module");
} else {
JsVar *moduleName = jsvFindChildFromVar(moduleList, id, true);
if (moduleName) jsvSetValueOfName(moduleName, moduleExport);
jsvUnLock(moduleExport);
}
jsvUnLock(moduleList);
}

View File

@@ -0,0 +1,21 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* JavaScript Functions for handling Modules
* ----------------------------------------------------------------------------
*/
#include "jsvar.h"
JsVar *jswrap_require(JsVar *modulename);
JsVar *jswrap_modules_getCached();
void jswrap_modules_removeCached(JsVar *id);
void jswrap_modules_removeAllCached();
void jswrap_modules_addCached(JsVar *id, JsVar *sourceCode);

View File

@@ -0,0 +1,332 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* This file is designed to be parsed during the build process
*
* JavaScript methods for Objects and Functions
* ----------------------------------------------------------------------------
*/
#include "jswrap_object.h"
#include "jsparse.h"
#include "jsinteractive.h"
/*JSON{ "type":"class",
"class" : "Hardware",
"check" : "jsvIsRoot(var)",
"description" : ["This is the built-in class for the Espruino device. It is the 'root scope', as 'Window' is for JavaScript on the desktop." ]
}*/
/*JSON{ "type":"class",
"class" : "Object",
"check" : "jsvIsObject(var)",
"description" : ["This is the built-in class for Objects" ]
}*/
/*JSON{ "type":"class",
"class" : "Function",
"check" : "jsvIsFunction(var)",
"description" : ["This is the built-in class for Functions" ]
}*/
/*JSON{ "type":"class",
"class" : "Integer",
"check" : "jsvIsInt(var)",
"description" : ["This is the built-in class for Integer values" ]
}*/
/*JSON{ "type":"class",
"class" : "Double",
"check" : "jsvIsFloat(var)",
"description" : ["This is the built-in class for Floating Point values" ]
}*/
/*JSON{ "type":"property", "class": "Object", "name" : "length",
"description" : "Find the length of the object",
"generate" : "jswrap_object_length",
"return" : ["JsVar", "The value of the string"]
}*/
JsVar *jswrap_object_length(JsVar *parent) {
if (jsvIsArray(parent)) {
return jsvNewFromInteger(jsvGetArrayLength(parent));
} else if (jsvIsArrayBuffer(parent)) {
return jsvNewFromInteger((JsVarInt)jsvGetArrayBufferLength(parent));
} else if (jsvIsString(parent)) {
return jsvNewFromInteger((JsVarInt)jsvGetStringLength(parent));
}
return 0;
}
/*JSON{ "type":"method", "class": "Object", "name" : "toString",
"description" : "Convert the Object to a string",
"generate" : "jswrap_object_toString",
"params" : [ [ "radix", "JsVar", "If the object is an integer, the radix (between 2 and 36) to use. NOTE: Setting a radix does not work on floating point numbers."] ],
"return" : ["JsVar", "A String representing the object"]
}*/
JsVar *jswrap_object_toString(JsVar *parent, JsVar *arg0) {
if (jsvIsInt(arg0) && jsvIsInt(parent)) {
JsVarInt radix = jsvGetInteger(arg0);
if (radix>=2 && radix<=36) {
char buf[JS_NUMBER_BUFFER_SIZE];
itoa(parent->varData.integer, buf, (unsigned int)radix);
return jsvNewFromString(buf);
}
}
return jsvAsString(parent, false);
}
/*JSON{ "type":"method", "class": "Object", "name" : "clone",
"description" : "Copy this object completely",
"generate" : "jswrap_object_clone",
"return" : ["JsVar", "A copy of this Object"]
}*/
JsVar *jswrap_object_clone(JsVar *parent) {
return jsvCopy(parent);
}
/*JSON{ "type":"staticmethod", "class": "Object", "name" : "keys",
"description" : "Return all enumerable keys of the given object",
"generate" : "jswrap_object_keys",
"params" : [ [ "object", "JsVar", "The object to return keys for"] ],
"return" : ["JsVar", "An array of strings - one for each key on the given object"]
}*/
JsVar *jswrap_object_keys(JsVar *obj) {
if (jsvIsIterable(obj)) {
bool (*checkerFunction)(JsVar*) = 0;
if (jsvIsFunction(obj)) checkerFunction = jsvIsInternalFunctionKey;
else if (jsvIsObject(obj)) checkerFunction = jsvIsInternalObjectKey;
JsVar *arr = jsvNewWithFlags(JSV_ARRAY);
if (!arr) return 0;
JsvIterator it;
jsvIteratorNew(&it, obj);
while (jsvIteratorHasElement(&it)) {
JsVar *key = jsvIteratorGetKey(&it);
if (!(checkerFunction && checkerFunction(key))) {
JsVar *name = jsvCopyNameOnly(key,false,false);
if (name) {
jsvArrayPushAndUnLock(arr, name);
}
}
jsvUnLock(key);
jsvIteratorNext(&it);
}
jsvIteratorFree(&it);
return arr;
} else {
jsWarn("Object.keys called on non-object");
return 0;
}
}
/*JSON{ "type":"method", "class": "Object", "name" : "on",
"description" : ["Register an event listener for this object, for instance ```http.on('data', function(d) {...})```. See Node.js's EventEmitter."],
"generate" : "jswrap_object_on",
"params" : [ [ "event", "JsVar", "The name of the event, for instance 'data'"],
[ "listener", "JsVar", "The listener to call when this event is received"] ]
}*/
void jswrap_object_on(JsVar *parent, JsVar *event, JsVar *listener) {
if (!jsvIsObject(parent)) {
jsWarn("Parent must be a proper object - not a String, Integer, etc.");
return;
}
if (!jsvIsString(event)) {
jsWarn("First argument to EventEmitter.on(..) must be a string");
return;
}
if (!jsvIsFunction(listener) && !jsvIsString(listener)) {
jsWarn("Second argument to EventEmitter.on(..) must be a function or a String (containing code)");
return;
}
char eventName[16] = "#on";
jsvGetString(event, &eventName[3], sizeof(eventName)-4);
JsVar *eventList = jsvFindChildFromString(parent, eventName, true);
JsVar *eventListeners = jsvSkipName(eventList);
if (jsvIsUndefined(eventListeners)) {
// just add
jsvSetValueOfName(eventList, listener);
} else {
if (jsvIsArray(eventListeners)) {
// we already have an array, just add to it
jsvArrayPush(eventListeners, listener);
} else {
// not an array - we need to make it an array
JsVar *arr = jsvNewWithFlags(JSV_ARRAY);
jsvArrayPush(arr, eventListeners);
jsvArrayPush(arr, listener);
jsvSetValueOfName(eventList, arr);
jsvUnLock(arr);
}
}
jsvUnLock(eventListeners);
jsvUnLock(eventList);
}
/*JSON{ "type":"method", "class": "Object", "name" : "emit",
"description" : ["Call the event listeners for this object, for instance ```http.emit('data', 'Foo')```. See Node.js's EventEmitter."],
"generate" : "jswrap_object_emit",
"params" : [ [ "event", "JsVar", "The name of the event, for instance 'data'"],
[ "v1", "JsVar", "Optional argument 1"],
[ "v2", "JsVar", "Optional argument 2"] ]
}*/
void jswrap_object_emit(JsVar *parent, JsVar *event, JsVar *v1, JsVar *v2) {
if (!jsvIsObject(parent)) {
jsWarn("Parent must be a proper object - not a String, Integer, etc.");
return;
}
if (!jsvIsString(event)) {
jsWarn("First argument to EventEmitter.emit(..) must be a string");
return;
}
char eventName[16] = "#on";
jsvGetString(event, &eventName[3], sizeof(eventName)-4);
jsiQueueObjectCallbacks(parent, eventName, v1, v2);
}
/*JSON{ "type":"method", "class": "Object", "name" : "removeAllListeners",
"description" : ["Removes all listeners, or those of the specified event."],
"generate" : "jswrap_object_removeAllListeners",
"params" : [ [ "event", "JsVar", "The name of the event, for instance 'data'"] ]
}*/
void jswrap_object_removeAllListeners(JsVar *parent, JsVar *event) {
if (!jsvIsObject(parent)) {
jsWarn("Parent must be a proper object - not a String, Integer, etc.");
return;
}
if (jsvIsString(event)) {
// remove the whole child containing listeners
char eventName[16] = "#on";
jsvGetString(event, &eventName[3], sizeof(eventName)-4);
JsVar *eventList = jsvFindChildFromString(parent, eventName, true);
if (eventList) {
jsvRemoveChild(parent, eventList);
jsvUnLock(eventList);
}
} else if (jsvIsUndefined(event)) {
// Eep. We must remove everything beginning with '#on'
JsObjectIterator it;
jsvObjectIteratorNew(&it, parent);
while (jsvObjectIteratorHasElement(&it)) {
JsVar *key = jsvObjectIteratorGetKey(&it);
jsvObjectIteratorNext(&it);
if (jsvIsString(key) &&
key->varData.str[0]=='#' &&
key->varData.str[1]=='o' &&
key->varData.str[2]=='n') {
// begins with #on - we must kill it
jsvRemoveChild(parent, key);
}
jsvUnLock(key);
}
jsvObjectIteratorFree(&it);
} else {
jsWarn("First argument to EventEmitter.removeAllListeners(..) must be a string, or undefined");
return;
}
}
// ------------------------------------------------------------------------------
/*JSON{ "type":"method", "class": "Function", "name" : "replaceWith",
"description" : ["This replaces the function with the one in the argument - while keeping the old function's scope. This allows inner functions to be edited, and is used when edit() is called on an inner function."],
"generate" : "jswrap_function_replaceWith",
"params" : [ [ "newFunc", "JsVar", "The new function to replace this function with"] ]
}*/
void jswrap_function_replaceWith(JsVar *oldFunc, JsVar *newFunc) {
if (!jsvIsFunction(newFunc)) {
jsWarn("First argument of replaceWith should be a function - ignoring");
return;
}
// Grab scope - the one thing we want to keep
JsVar *scope = jsvFindChildFromString(oldFunc, JSPARSE_FUNCTION_SCOPE_NAME, false);
// so now remove all existing entries
jsvRemoveAllChildren(oldFunc);
// now re-add scope
jsvAddName(oldFunc, scope);
jsvUnLock(scope);
// now re-add other entries
JsObjectIterator it;
jsvObjectIteratorNew(&it, newFunc);
while (jsvObjectIteratorHasElement(&it)) {
JsVar *el = jsvObjectIteratorGetKey(&it);
jsvObjectIteratorNext(&it);
if (!jsvIsStringEqual(el, JSPARSE_FUNCTION_SCOPE_NAME)) {
JsVar *copy = jsvCopy(el);
if (copy) {
jsvAddName(oldFunc, copy);
jsvUnLock(copy);
}
}
}
jsvObjectIteratorFree(&it);
}
/*JSON{ "type":"method", "class": "Function", "name" : "call",
"description" : ["This executes the function with the supplied 'this' argument and parameters"],
"generate" : "jswrap_function_call",
"params" : [ [ "this", "JsVar", "The value to use as the 'this' argument when executing the function"],
[ "a", "JsVar", "Optional Parameter 1"],
[ "b", "JsVar", "Optional Parameter 2"],
[ "c", "JsVar", "Optional Parameter 3"],
[ "d", "JsVar", "Optional Parameter 4"]
],
"return" : [ "JsVar", "The return value of executing this function" ]
}*/
JsVar *jswrap_function_call(JsVar *parent, JsVar *thisArg, JsVar *a, JsVar *b, JsVar *c, JsVar *d) {
JsVar *args[4] = {a,b,c,d};
int argC = 0;
while (argC<4 && args[argC]!=0) argC++;
return jspeFunctionCall(parent, 0, thisArg, false, argC, args);
}
/*JSON{ "type":"method", "class": "Function", "name" : "apply",
"description" : ["This executes the function with the supplied 'this' argument and parameters"],
"generate" : "jswrap_function_apply",
"params" : [ [ "this", "JsVar", "The value to use as the 'this' argument when executing the function"],
[ "args", "JsVar", "Optional Array of Aruments"]
],
"return" : [ "JsVar", "The return value of executing this function" ]
}*/
JsVar *jswrap_function_apply(JsVar *parent, JsVar *thisArg, JsVar *argsArray) {
unsigned int i;
JsVar **args = 0;
size_t argC = 0;
if (jsvIsArray(argsArray)) {
argC = (unsigned int)jsvGetArrayLength(argsArray);
if (argC>64) argC=64; // sanity
#ifdef RT_USING_JS
args = (JsVar**)rt_malloc((size_t)argC * sizeof(JsVar*));
#else
args = (JsVar**)alloca((size_t)argC * sizeof(JsVar*));
#endif
for (i=0;i<argC;i++) args[i] = 0;
JsArrayIterator it;
jsvArrayIteratorNew(&it, argsArray);
while (jsvArrayIteratorHasElement(&it)) {
JsVarInt idx = jsvGetIntegerAndUnLock(jsvArrayIteratorGetIndex(&it));
if (idx>=0 && idx<argC) {
assert(!args[idx]); // just in case there were dups
args[idx] = jsvArrayIteratorGetElement(&it);
}
jsvArrayIteratorNext(&it);
}
jsvArrayIteratorFree(&it);
} else if (!jsvIsUndefined(argsArray)) {
jsWarn("Second argument to Function.apply must be an array");
}
JsVar *r = jspeFunctionCall(parent, 0, thisArg, false, (int)argC, args);
for (i=0;i<argC;i++) jsvUnLock(args[i]);
#ifdef RT_USING_JS
rt_free(args);
#else
#error "please define RT_USING_JS on rtconfig.h"
#endif
return r;
}

View File

@@ -0,0 +1,27 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* JavaScript methods for Objects and Functions
* ----------------------------------------------------------------------------
*/
#include "jsvar.h"
JsVar *jswrap_object_length(JsVar *parent);
JsVar *jswrap_object_toString(JsVar *parent, JsVar *arg0);
JsVar *jswrap_object_clone(JsVar *parent);
JsVar *jswrap_object_keys(JsVar *obj);
void jswrap_object_on(JsVar *parent, JsVar *event, JsVar *listener);
void jswrap_object_emit(JsVar *parent, JsVar *event, JsVar *v1, JsVar *v2);
void jswrap_object_removeAllListeners(JsVar *parent, JsVar *event);
void jswrap_function_replaceWith(JsVar *parent, JsVar *newFunc);
JsVar *jswrap_function_call(JsVar *parent, JsVar *thisArg, JsVar *a, JsVar *b, JsVar *c, JsVar *d);
JsVar *jswrap_function_apply(JsVar *parent, JsVar *thisArg, JsVar *argsArray);

Some files were not shown because too many files have changed in this diff Show More