Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
3
Task/Safe-addition/00-META.yaml
Normal file
3
Task/Safe-addition/00-META.yaml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Safe_addition
|
||||
note: Arithmetic operations
|
||||
25
Task/Safe-addition/00-TASK.txt
Normal file
25
Task/Safe-addition/00-TASK.txt
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
Implementation of [[wp:Interval_arithmetic|interval arithmetic]] and more generally fuzzy number arithmetic require operations that yield safe upper and lower bounds of the exact result.
|
||||
|
||||
For example, for an addition, it is the operations <big> +↑ </big> and <big> +↓ </big> defined as: <big> ''a'' +↓ ''b'' ≤ ''a'' + ''b'' ≤ ''a'' +↑ ''b''. </big>
|
||||
|
||||
Additionally it is desired that the width of the interval <big> (''a'' +↑ ''b'') - (''a'' +↓ ''b'') </big> would be about the machine epsilon after removing the exponent part.
|
||||
|
||||
Differently to the standard floating-point arithmetic, safe interval arithmetic is '''accurate''' (but still imprecise).
|
||||
|
||||
I.E.: the result of each defined operation contains (though does not identify) the exact mathematical outcome.
|
||||
|
||||
Usually a [[wp:Floating_Point_Unit|FPU's]] have machine <big> +,-,*,/ </big> operations accurate within the machine precision.
|
||||
|
||||
To illustrate it, let us consider a machine with decimal floating-point arithmetic that has the precision is '''3''' decimal points.
|
||||
|
||||
If the result of the machine addition is <big> 1.23, </big> then the exact mathematical result is within the interval <big> ]1.22, 1.24[. </big>
|
||||
|
||||
When the machine rounds towards zero, then the exact result is within <big> [1.23,1.24[. </big> This is the basis for an implementation of safe addition.
|
||||
|
||||
|
||||
;Task;
|
||||
Show how <big> +↓ </big> and <big> +↑ </big> can be implemented in your language using the standard floating-point type.
|
||||
|
||||
Define an interval type based on the standard floating-point one, and implement an interval-valued addition of two floating-point numbers considering them exact, in short an operation that yields the interval <big> [''a'' +↓ ''b'', ''a'' +↑ ''b'']. </big>
|
||||
<br><br>
|
||||
|
||||
4
Task/Safe-addition/Ada/safe-addition-1.ada
Normal file
4
Task/Safe-addition/Ada/safe-addition-1.ada
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
type Interval is record
|
||||
Lower : Float;
|
||||
Upper : Float;
|
||||
end record;
|
||||
19
Task/Safe-addition/Ada/safe-addition-2.ada
Normal file
19
Task/Safe-addition/Ada/safe-addition-2.ada
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
function "+" (A, B : Float) return Interval is
|
||||
Result : constant Float := A + B;
|
||||
begin
|
||||
if Result < 0.0 then
|
||||
if Float'Machine_Rounds then
|
||||
return (Float'Adjacent (Result, Float'First), Float'Adjacent (Result, 0.0));
|
||||
else
|
||||
return (Float'Adjacent (Result, Float'First), Result);
|
||||
end if;
|
||||
elsif Result > 0.0 then
|
||||
if Float'Machine_Rounds then
|
||||
return (Float'Adjacent (Result, 0.0), Float'Adjacent (Result, Float'Last));
|
||||
else
|
||||
return (Result, Float'Adjacent (Result, Float'Last));
|
||||
end if;
|
||||
else -- Underflow
|
||||
return (Float'Adjacent (0.0, Float'First), Float'Adjacent (0.0, Float'Last));
|
||||
end if;
|
||||
end "+";
|
||||
10
Task/Safe-addition/Ada/safe-addition-3.ada
Normal file
10
Task/Safe-addition/Ada/safe-addition-3.ada
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
with Ada.Text_IO; use Ada.Text_IO;
|
||||
procedure Test_Interval_Addition is
|
||||
-- Definitions from above
|
||||
procedure Put (I : Interval) is
|
||||
begin
|
||||
Put (Long_Float'Image (Long_Float (I.Lower)) & "," & Long_Float'Image (Long_Float (I.Upper)));
|
||||
end Put;
|
||||
begin
|
||||
Put (1.14 + 2000.0);
|
||||
end Test_Interval_Addition;
|
||||
14
Task/Safe-addition/AutoHotkey/safe-addition.ahk
Normal file
14
Task/Safe-addition/AutoHotkey/safe-addition.ahk
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
Msgbox % IntervalAdd(1,2) ; [2.999999,3.000001]
|
||||
|
||||
SetFormat, FloatFast, 0.20
|
||||
Msgbox % IntervalAdd(1,2) ; [2.99999999999999910000,3.00000000000000090000]
|
||||
|
||||
;In v1.0.48+, floating point variables have about 15 digits of precision internally
|
||||
;unless SetFormat Float (i.e. the slow mode) is present anywhere in the script.
|
||||
;In that case, the stored precision of floating point numbers is determined by A_FormatFloat.
|
||||
;As there is no way for this function to know whether this is the case or not,
|
||||
;it conservatively uses A_FormatFloat in all cases.
|
||||
IntervalAdd(a,b){
|
||||
err:=0.1**(SubStr(A_FormatFloat,3) > 15 ? 15 : SubStr(A_FormatFloat,3))
|
||||
Return "[" a+b-err ","a+b+err "]"
|
||||
}
|
||||
43
Task/Safe-addition/C++/safe-addition.cpp
Normal file
43
Task/Safe-addition/C++/safe-addition.cpp
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#include <iostream>
|
||||
#include <tuple>
|
||||
|
||||
union conv {
|
||||
int i;
|
||||
float f;
|
||||
};
|
||||
|
||||
float nextUp(float d) {
|
||||
if (isnan(d) || d == -INFINITY || d == INFINITY) return d;
|
||||
if (d == 0.0) return FLT_EPSILON;
|
||||
|
||||
conv c;
|
||||
c.f = d;
|
||||
c.i++;
|
||||
|
||||
return c.f;
|
||||
}
|
||||
|
||||
float nextDown(float d) {
|
||||
if (isnan(d) || d == -INFINITY || d == INFINITY) return d;
|
||||
if (d == 0.0) return -FLT_EPSILON;
|
||||
|
||||
conv c;
|
||||
c.f = d;
|
||||
c.i--;
|
||||
|
||||
return c.f;
|
||||
}
|
||||
|
||||
auto safeAdd(float a, float b) {
|
||||
return std::make_tuple(nextDown(a + b), nextUp(a + b));
|
||||
}
|
||||
|
||||
int main() {
|
||||
float a = 1.20f;
|
||||
float b = 0.03f;
|
||||
|
||||
auto result = safeAdd(a, b);
|
||||
printf("(%f + %f) is in the range (%0.16f, %0.16f)\n", a, b, std::get<0>(result), std::get<1>(result));
|
||||
|
||||
return 0;
|
||||
}
|
||||
40
Task/Safe-addition/C-sharp/safe-addition.cs
Normal file
40
Task/Safe-addition/C-sharp/safe-addition.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
using System;
|
||||
|
||||
namespace SafeAddition {
|
||||
class Program {
|
||||
static float NextUp(float d) {
|
||||
if (d == 0.0) return float.Epsilon;
|
||||
if (float.IsNaN(d) || float.IsNegativeInfinity(d) || float.IsPositiveInfinity(d)) return d;
|
||||
|
||||
byte[] bytes = BitConverter.GetBytes(d);
|
||||
int dl = BitConverter.ToInt32(bytes, 0);
|
||||
dl++;
|
||||
bytes = BitConverter.GetBytes(dl);
|
||||
|
||||
return BitConverter.ToSingle(bytes, 0);
|
||||
}
|
||||
|
||||
static float NextDown(float d) {
|
||||
if (d == 0.0) return -float.Epsilon;
|
||||
if (float.IsNaN(d) || float.IsNegativeInfinity(d) || float.IsPositiveInfinity(d)) return d;
|
||||
|
||||
byte[] bytes = BitConverter.GetBytes(d);
|
||||
int dl = BitConverter.ToInt32(bytes, 0);
|
||||
dl--;
|
||||
bytes = BitConverter.GetBytes(dl);
|
||||
|
||||
return BitConverter.ToSingle(bytes, 0);
|
||||
}
|
||||
|
||||
static Tuple<float, float> SafeAdd(float a, float b) {
|
||||
return new Tuple<float, float>(NextDown(a + b), NextUp(a + b));
|
||||
}
|
||||
|
||||
static void Main(string[] args) {
|
||||
float a = 1.20f;
|
||||
float b = 0.03f;
|
||||
|
||||
Console.WriteLine("({0} + {1}) is in the range {2}", a, b, SafeAdd(a, b));
|
||||
}
|
||||
}
|
||||
}
|
||||
50
Task/Safe-addition/C/safe-addition-1.c
Normal file
50
Task/Safe-addition/C/safe-addition-1.c
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#include <fenv.h> /* fegetround(), fesetround() */
|
||||
#include <stdio.h> /* printf() */
|
||||
|
||||
/*
|
||||
* Calculates an interval for a + b.
|
||||
* interval[0] <= a + b
|
||||
* a + b <= interval[1]
|
||||
*/
|
||||
void
|
||||
safe_add(volatile double interval[2], volatile double a, volatile double b)
|
||||
{
|
||||
#pragma STDC FENV_ACCESS ON
|
||||
unsigned int orig;
|
||||
|
||||
orig = fegetround();
|
||||
fesetround(FE_DOWNWARD); /* round to -infinity */
|
||||
interval[0] = a + b;
|
||||
fesetround(FE_UPWARD); /* round to +infinity */
|
||||
interval[1] = a + b;
|
||||
fesetround(orig);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
const double nums[][2] = {
|
||||
{1, 2},
|
||||
{0.1, 0.2},
|
||||
{1e100, 1e-100},
|
||||
{1e308, 1e308},
|
||||
};
|
||||
double ival[2];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(nums) / sizeof(nums[0]); i++) {
|
||||
/*
|
||||
* Calculate nums[i][0] + nums[i][1].
|
||||
*/
|
||||
safe_add(ival, nums[i][0], nums[i][1]);
|
||||
|
||||
/*
|
||||
* Print the result. %.17g gives the best output.
|
||||
* %.16g or plain %g gives not enough digits.
|
||||
*/
|
||||
printf("%.17g + %.17g =\n", nums[i][0], nums[i][1]);
|
||||
printf(" [%.17g, %.17g]\n", ival[0], ival[1]);
|
||||
printf(" size %.17g\n\n", ival[1] - ival[0]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
49
Task/Safe-addition/C/safe-addition-2.c
Normal file
49
Task/Safe-addition/C/safe-addition-2.c
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#include <float.h> /* _controlfp() */
|
||||
#include <stdio.h> /* printf() */
|
||||
|
||||
/*
|
||||
* Calculates an interval for a + b.
|
||||
* interval[0] <= a + b
|
||||
* a + b <= interval[1]
|
||||
*/
|
||||
void
|
||||
safe_add(volatile double interval[2], volatile double a, volatile double b)
|
||||
{
|
||||
unsigned int orig;
|
||||
|
||||
orig = _controlfp(0, 0);
|
||||
_controlfp(_RC_DOWN, _MCW_RC); /* round to -infinity */
|
||||
interval[0] = a + b;
|
||||
_controlfp(_RC_UP, _MCW_RC); /* round to +infinity */
|
||||
interval[1] = a + b;
|
||||
_controlfp(orig, _MCW_RC);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
const double nums[][2] = {
|
||||
{1, 2},
|
||||
{0.1, 0.2},
|
||||
{1e100, 1e-100},
|
||||
{1e308, 1e308},
|
||||
};
|
||||
double ival[2];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(nums) / sizeof(nums[0]); i++) {
|
||||
/*
|
||||
* Calculate nums[i][0] + nums[i][1].
|
||||
*/
|
||||
safe_add(ival, nums[i][0], nums[i][1]);
|
||||
|
||||
/*
|
||||
* Print the result. %.17g gives the best output.
|
||||
* %.16g or plain %g gives not enough digits.
|
||||
*/
|
||||
printf("%.17g + %.17g =\n", nums[i][0], nums[i][1]);
|
||||
printf(" [%.17g, %.17g]\n", ival[0], ival[1]);
|
||||
printf(" size %.17g\n\n", ival[1] - ival[0]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
49
Task/Safe-addition/C/safe-addition-3.c
Normal file
49
Task/Safe-addition/C/safe-addition-3.c
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#include <ieeefp.h> /* fpsetround() */
|
||||
#include <stdio.h> /* printf() */
|
||||
|
||||
/*
|
||||
* Calculates an interval for a + b.
|
||||
* interval[0] <= a + b
|
||||
* a + b <= interval[1]
|
||||
*/
|
||||
void
|
||||
safe_add(volatile double interval[2], volatile double a, volatile double b)
|
||||
{
|
||||
fp_rnd orig;
|
||||
|
||||
orig = fpsetround(FP_RM); /* round to -infinity */
|
||||
interval[0] = a + b;
|
||||
fpsetround(FP_RP); /* round to +infinity */
|
||||
interval[1] = a + b;
|
||||
fpsetround(orig);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
const double nums[][2] = {
|
||||
{1, 2},
|
||||
{0.1, 0.2},
|
||||
{1e100, 1e-100},
|
||||
{1e308, 1e308},
|
||||
};
|
||||
double ival[2];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(nums) / sizeof(nums[0]); i++) {
|
||||
/*
|
||||
* Calculate nums[i][0] + nums[i][1].
|
||||
*/
|
||||
safe_add(ival, nums[i][0], nums[i][1]);
|
||||
|
||||
/*
|
||||
* Print the result. With OpenBSD libc, %.17g gives
|
||||
* the best output; %.16g or plain %g gives not enough
|
||||
* digits.
|
||||
*/
|
||||
printf("%.17g + %.17g =\n", nums[i][0], nums[i][1]);
|
||||
printf(" [%.17g, %.17g]\n", ival[0], ival[1]);
|
||||
printf(" size %.17g\n\n", ival[1] - ival[0]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
16
Task/Safe-addition/D/safe-addition.d
Normal file
16
Task/Safe-addition/D/safe-addition.d
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import std.traits;
|
||||
auto safeAdd(T)(T a, T b)
|
||||
if (isFloatingPoint!T) {
|
||||
import std.math; // nexDown, nextUp
|
||||
import std.typecons; // tuple
|
||||
return tuple!("d", "u")(nextDown(a+b), nextUp(a+b));
|
||||
}
|
||||
|
||||
import std.stdio;
|
||||
void main() {
|
||||
auto a = 1.2;
|
||||
auto b = 0.03;
|
||||
|
||||
auto r = safeAdd(a, b);
|
||||
writefln("(%s + %s) is in the range %0.16f .. %0.16f", a, b, r.d, r.u);
|
||||
}
|
||||
17
Task/Safe-addition/E/safe-addition-1.e
Normal file
17
Task/Safe-addition/E/safe-addition-1.e
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
def makeInterval(a :float64, b :float64) {
|
||||
require(a <= b)
|
||||
def interval {
|
||||
to least() { return a }
|
||||
to greatest() { return b }
|
||||
to __printOn(out) {
|
||||
out.print("[", a, ", ", b, "]")
|
||||
}
|
||||
to add(other) {
|
||||
require(a <=> b)
|
||||
require(other.least() <=> other.greatest())
|
||||
def result := a + other.least()
|
||||
return makeInterval(result.previous(), result.next())
|
||||
}
|
||||
}
|
||||
return interval
|
||||
}
|
||||
2
Task/Safe-addition/E/safe-addition-2.e
Normal file
2
Task/Safe-addition/E/safe-addition-2.e
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
? makeInterval(1.14, 1.14) + makeInterval(2000.0, 2000.0)
|
||||
# value: [2001.1399999999999, 2001.1400000000003]
|
||||
15
Task/Safe-addition/Forth/safe-addition.fth
Normal file
15
Task/Safe-addition/Forth/safe-addition.fth
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
c-library m
|
||||
s" m" add-lib
|
||||
\c #include <math.h>
|
||||
c-function fnextafter nextafter r r -- r
|
||||
end-c-library
|
||||
|
||||
s" MAX-FLOAT" environment? drop fconstant MAX-FLOAT
|
||||
|
||||
: fstepdown ( F: r1 -- r2 )
|
||||
MAX-FLOAT fnegate fnextafter ;
|
||||
: fstepup ( F: r1 -- r2 )
|
||||
MAX-FLOAT fnextafter ;
|
||||
|
||||
: savef+ ( F: r1 r2 -- r3 r4 ) \ r4 <= r1+r2 <= r3
|
||||
f+ fdup fstepup fswap fstepdown ;
|
||||
30
Task/Safe-addition/Go/safe-addition.go
Normal file
30
Task/Safe-addition/Go/safe-addition.go
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// type requested by task
|
||||
type interval struct {
|
||||
lower, upper float64
|
||||
}
|
||||
|
||||
// a constructor
|
||||
func stepAway(x float64) interval {
|
||||
return interval {
|
||||
math.Nextafter(x, math.Inf(-1)),
|
||||
math.Nextafter(x, math.Inf(1))}
|
||||
}
|
||||
|
||||
// function requested by task
|
||||
func safeAdd(a, b float64) interval {
|
||||
return stepAway(a + b)
|
||||
|
||||
}
|
||||
|
||||
// example
|
||||
func main() {
|
||||
a, b := 1.2, .03
|
||||
fmt.Println(a, b, safeAdd(a, b))
|
||||
}
|
||||
27
Task/Safe-addition/Hare/safe-addition.hare
Normal file
27
Task/Safe-addition/Hare/safe-addition.hare
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
use fmt;
|
||||
use math;
|
||||
|
||||
type interval = struct {a: f64, b: f64};
|
||||
|
||||
export fn main() void = {
|
||||
const a: [_](f64, f64) = [
|
||||
(1.0f64, 2.0f64),
|
||||
(0.1f64, 0.2f64),
|
||||
(1e100f64, 1e-100f64),
|
||||
(1e308f64, 1e308f64)];
|
||||
|
||||
for (let i = 0z; i < len(a); i += 1) {
|
||||
let res = safe_add(a[i].0, a[i].1);
|
||||
fmt::printfln("{} + {} is within ({}, {})", a[i].0, a[i].1, res.a, res.b)!;
|
||||
};
|
||||
};
|
||||
|
||||
fn safe_add(a: f64, b: f64) interval = {
|
||||
let orig = math::getround();
|
||||
math::setround(math::fround::DOWNWARD);
|
||||
let r0 = a + b;
|
||||
math::setround(math::fround::UPWARD);
|
||||
let r1 = a + b;
|
||||
math::setround(orig);
|
||||
return interval{a = r0, b = r1};
|
||||
};
|
||||
4
Task/Safe-addition/J/safe-addition.j
Normal file
4
Task/Safe-addition/J/safe-addition.j
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
err =. 2^ 53-~ 2 <.@^. | NB. get the size of one-half unit in the last place
|
||||
safeadd =. + (-,+) +&err
|
||||
0j15": 1.14 safeadd 2000.0 NB. print with 15 digits after the decimal
|
||||
2001.139999999999873 2001.140000000000327
|
||||
20
Task/Safe-addition/Java/safe-addition.java
Normal file
20
Task/Safe-addition/Java/safe-addition.java
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
public class SafeAddition {
|
||||
private static double stepDown(double d) {
|
||||
return Math.nextAfter(d, Double.NEGATIVE_INFINITY);
|
||||
}
|
||||
|
||||
private static double stepUp(double d) {
|
||||
return Math.nextUp(d);
|
||||
}
|
||||
|
||||
private static double[] safeAdd(double a, double b) {
|
||||
return new double[]{stepDown(a + b), stepUp(a + b)};
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
double a = 1.2;
|
||||
double b = 0.03;
|
||||
double[] result = safeAdd(a, b);
|
||||
System.out.printf("(%.2f + %.2f) is in the range %.16f..%.16f", a, b, result[0], result[1]);
|
||||
}
|
||||
}
|
||||
19
Task/Safe-addition/Julia/safe-addition.julia
Normal file
19
Task/Safe-addition/Julia/safe-addition.julia
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
julia> using IntervalArithmetic
|
||||
|
||||
julia> n = 2.0
|
||||
2.0
|
||||
|
||||
julia> @interval 2n/3 + 1
|
||||
[2.33333, 2.33334]
|
||||
|
||||
julia> showall(ans)
|
||||
Interval(2.333333333333333, 2.3333333333333335)
|
||||
|
||||
julia> a = @interval(0.1, 0.3)
|
||||
[0.0999999, 0.300001]
|
||||
|
||||
julia> b = @interval(0.3, 0.6)
|
||||
[0.299999, 0.600001]
|
||||
|
||||
julia> a + b
|
||||
[0.399999, 0.900001]
|
||||
13
Task/Safe-addition/Kotlin/safe-addition.kotlin
Normal file
13
Task/Safe-addition/Kotlin/safe-addition.kotlin
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// version 1.1.2
|
||||
|
||||
fun stepDown(d: Double) = Math.nextAfter(d, Double.NEGATIVE_INFINITY)
|
||||
|
||||
fun stepUp(d: Double) = Math.nextUp(d)
|
||||
|
||||
fun safeAdd(a: Double, b: Double) = stepDown(a + b).rangeTo(stepUp(a + b))
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val a = 1.2
|
||||
val b = 0.03
|
||||
println("($a + $b) is in the range ${safeAdd(a, b)}")
|
||||
}
|
||||
20
Task/Safe-addition/Nim/safe-addition.nim
Normal file
20
Task/Safe-addition/Nim/safe-addition.nim
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import fenv, strutils
|
||||
|
||||
proc `++`(a, b: float): tuple[lower, upper: float] =
|
||||
let
|
||||
a {.volatile.} = a
|
||||
b {.volatile.} = b
|
||||
orig = fegetround()
|
||||
discard fesetround FE_DOWNWARD
|
||||
result.lower = a + b
|
||||
discard fesetround FE_UPWARD
|
||||
result.upper = a + b
|
||||
discard fesetround orig
|
||||
|
||||
proc ff(a: float): string = a.formatFloat(ffDefault, 17)
|
||||
|
||||
for x, y in [(1.0, 2.0), (0.1, 0.2), (1e100, 1e-100), (1e308, 1e308)].items:
|
||||
let (d,u) = x ++ y
|
||||
echo x.ff, " + ", y.ff, " ="
|
||||
echo " [", d.ff, ", ", u.ff, "]"
|
||||
echo " size ", (u - d).ff, "\n"
|
||||
11
Task/Safe-addition/Perl/safe-addition.pl
Normal file
11
Task/Safe-addition/Perl/safe-addition.pl
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
use Data::IEEE754::Tools <nextUp nextDown>;
|
||||
|
||||
sub safe_add {
|
||||
my($a,$b) = @_;
|
||||
my $c = $a + $b;
|
||||
return $c, nextDown($c), nextUp($c)
|
||||
}
|
||||
|
||||
printf "%.17f (%.17f, %.17f)\n", safe_add (1/9,1/7);
|
||||
55
Task/Safe-addition/Phix/safe-addition.phix
Normal file
55
Task/Safe-addition/Phix/safe-addition.phix
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
-->
|
||||
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">VM</span><span style="color: #0000FF;">\</span><span style="color: #000000;">pFPU</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> <span style="color: #000080;font-style:italic;">-- :%down53 etc</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">safe_add</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">low</span><span style="color: #0000FF;">,</span><span style="color: #000000;">high</span>
|
||||
<span style="color: #000080;font-style:italic;">-- NB: be sure to restore the usual/default rounding!</span>
|
||||
#ilASM{
|
||||
[32]
|
||||
lea esi,[a]
|
||||
call :%pLoadFlt
|
||||
lea esi,[b]
|
||||
call :%pLoadFlt
|
||||
fld st0
|
||||
call :%down53
|
||||
fadd st0,st2
|
||||
lea edi,[low]
|
||||
call :%pStoreFlt
|
||||
call :%up53
|
||||
faddp
|
||||
lea edi,[high]
|
||||
call :%pStoreFlt
|
||||
call :%near53 -- usual/default
|
||||
[64]
|
||||
lea rsi,[a]
|
||||
call :%pLoadFlt
|
||||
lea rsi,[b]
|
||||
call :%pLoadFlt
|
||||
fld st0
|
||||
call :%down64
|
||||
fadd st0,st2
|
||||
lea rdi,[low]
|
||||
call :%pStoreFlt
|
||||
call :%up64
|
||||
faddp
|
||||
lea rdi,[high]
|
||||
call :%pStoreFlt
|
||||
call :%near64 -- usual/default
|
||||
[]
|
||||
}
|
||||
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">low</span><span style="color: #0000FF;">,</span><span style="color: #000000;">high</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">nums</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">0.1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0.2</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">1e100</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1e-100</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">1e308</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1e308</span><span style="color: #0000FF;">}}</span>
|
||||
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nums</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">nums</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">low</span><span style="color: #0000FF;">,</span><span style="color: #000000;">high</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">safe_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%.16g + %.16g =\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">});</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" [%.16g, %.16g]\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">low</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">high</span><span style="color: #0000FF;">});</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" size %.16g\n\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">high</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">low</span><span style="color: #0000FF;">);</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<!--
|
||||
5
Task/Safe-addition/Python/safe-addition.py
Normal file
5
Task/Safe-addition/Python/safe-addition.py
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
>>> sum([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1])
|
||||
0.9999999999999999
|
||||
>>> from math import fsum
|
||||
>>> fsum([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1])
|
||||
1.0
|
||||
5
Task/Safe-addition/REXX/safe-addition.rexx
Normal file
5
Task/Safe-addition/REXX/safe-addition.rexx
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
numeric digits 1000 /*defines precision to be 1,000 decimal digits. */
|
||||
|
||||
y=digits() /*sets Y to existing number of decimal digits.*/
|
||||
|
||||
numeric digits y + y%10 /*increase the (numeric) decimal digits by 10%.*/
|
||||
27
Task/Safe-addition/Racket/safe-addition.rkt
Normal file
27
Task/Safe-addition/Racket/safe-addition.rkt
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#lang racket
|
||||
|
||||
;; 1. Racket has exact unlimited integers and fractions, which can be
|
||||
;; used to perform exact operations. For example, given an inexact
|
||||
;; flonum, we can convert it to an exact fraction and work with that:
|
||||
(define (exact+ x y)
|
||||
(+ (inexact->exact x) (inexact->exact y)))
|
||||
;; (A variant of this would be to keep all numbers exact, so the default
|
||||
;; operations never get to inexact numbers)
|
||||
|
||||
;; 2. We can implement the required operation using a bunch of
|
||||
;; functionality provided by the math library, for example, use
|
||||
;; `flnext' and `flprev' to get the surrounding numbers for both
|
||||
;; inputs and use them to produce the resulting interval:
|
||||
(require math)
|
||||
(define (interval+ x y)
|
||||
(cons (+ (flprev x) (flprev y)) (+ (flnext x) (flnext y))))
|
||||
(interval+ 1.14 2000.0) ; -> '(2001.1399999999999 . 2001.1400000000003)
|
||||
;; (Note: I'm not a numeric expert in any way, so there must be room for
|
||||
;; improvement here...)
|
||||
|
||||
;; 3. Yet another option is to use the math library's bigfloats, with an
|
||||
;; arbitrary precision:
|
||||
(bf-precision 1024) ; 1024 bit floats
|
||||
;; add two numbers, specified as strings to avoid rounding of number
|
||||
;; literals
|
||||
(bf+ (bf "1.14") (bf "2000.0"))
|
||||
28
Task/Safe-addition/Raku/safe-addition.raku
Normal file
28
Task/Safe-addition/Raku/safe-addition.raku
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
say "Floating points: (Nums)";
|
||||
say "Error: " ~ (2**-53).Num;
|
||||
|
||||
sub infix:<±+> (Num $a, Num $b) {
|
||||
my \ε = (2**-53).Num;
|
||||
$a - ε + $b, $a + ε + $b,
|
||||
}
|
||||
|
||||
printf "%4.16f .. %4.16f\n", (1.14e0 ±+ 2e3);
|
||||
|
||||
say "\nRationals:";
|
||||
|
||||
say ".1 + .2 is exactly equal to .3: ", .1 + .2 === .3;
|
||||
|
||||
say "\nLarge denominators require explicit coercion to FatRats:";
|
||||
say "Sum of inverses of the first 500 natural numbers:";
|
||||
my $sum = sum (1..500).map: { FatRat.new(1,$_) };
|
||||
say $sum;
|
||||
say $sum.nude;
|
||||
|
||||
{
|
||||
say "\nRat stringification may not show full precision for terminating fractions by default.";
|
||||
say "Use a module to get full precision.";
|
||||
use Rat::Precise; # module loading is scoped to the enclosing block
|
||||
my $rat = 1.5**63;
|
||||
say "\nRaku default stringification for 1.5**63:\n" ~ $rat; # standard stringification
|
||||
say "\nRat::Precise stringification for 1.5**63:\n" ~$rat.precise; # full precision
|
||||
}
|
||||
23
Task/Safe-addition/Ruby/safe-addition.rb
Normal file
23
Task/Safe-addition/Ruby/safe-addition.rb
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
require 'bigdecimal'
|
||||
require 'bigdecimal/util' # String#to_d
|
||||
|
||||
def safe_add(a, b, prec)
|
||||
a, b = a.to_d, b.to_d
|
||||
rm = BigDecimal::ROUND_MODE
|
||||
orig = BigDecimal.mode(rm)
|
||||
|
||||
BigDecimal.mode(rm, BigDecimal::ROUND_FLOOR)
|
||||
low = a.add(b, prec)
|
||||
|
||||
BigDecimal.mode(rm, BigDecimal::ROUND_CEILING)
|
||||
high = a.add(b, prec)
|
||||
|
||||
BigDecimal.mode(rm, orig)
|
||||
low..high
|
||||
end
|
||||
|
||||
[["1", "2"],
|
||||
["0.1", "0.2"],
|
||||
["0.1", "0.00002"],
|
||||
["0.1", "-0.00002"],
|
||||
].each { |a, b| puts "#{a} + #{b} = #{safe_add(a, b, 3)}" }
|
||||
13
Task/Safe-addition/Scala/safe-addition.scala
Normal file
13
Task/Safe-addition/Scala/safe-addition.scala
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
object SafeAddition extends App {
|
||||
val (a, b) = (1.2, 0.03)
|
||||
val result = safeAdd(a, b)
|
||||
|
||||
private def safeAdd(a: Double, b: Double) = Seq(stepDown(a + b), stepUp(a + b))
|
||||
|
||||
private def stepDown(d: Double) = Math.nextAfter(d, Double.NegativeInfinity)
|
||||
|
||||
private def stepUp(d: Double) = Math.nextUp(d)
|
||||
|
||||
println(f"($a%.2f + $b%.2f) is in the range ${result.head}%.16f .. ${result.last}%.16f")
|
||||
|
||||
}
|
||||
4
Task/Safe-addition/Swift/safe-addition.swift
Normal file
4
Task/Safe-addition/Swift/safe-addition.swift
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
let a = 1.2
|
||||
let b = 0.03
|
||||
|
||||
print("\(a) + \(b) is in the range \((a + b).nextDown)...\((a + b).nextUp)")
|
||||
12
Task/Safe-addition/Tcl/safe-addition-1.tcl
Normal file
12
Task/Safe-addition/Tcl/safe-addition-1.tcl
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
package require critcl
|
||||
package provide stepaway 1.0
|
||||
critcl::ccode {
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
}
|
||||
critcl::cproc stepup {double value} double {
|
||||
return nextafter(value, DBL_MAX);
|
||||
}
|
||||
critcl::cproc stepdown {double value} double {
|
||||
return nextafter(value, -DBL_MAX);
|
||||
}
|
||||
5
Task/Safe-addition/Tcl/safe-addition-2.tcl
Normal file
5
Task/Safe-addition/Tcl/safe-addition-2.tcl
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
package require stepaway
|
||||
proc safe+ {a b} {
|
||||
set val [expr {double($a) + $b}]
|
||||
return [list [stepdown $val] [stepup $val]]
|
||||
}
|
||||
13
Task/Safe-addition/Transd/safe-addition.transd
Normal file
13
Task/Safe-addition/Transd/safe-addition.transd
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#lang transd
|
||||
|
||||
MainModule : {
|
||||
a: 1.2,
|
||||
b: 0.03,
|
||||
|
||||
safeAdd: (λ d Double() e Double()
|
||||
(ret [(decr (+ d e)), (incr (+ d e))])),
|
||||
|
||||
_start: (λ
|
||||
(lout "(+ " a " " b ") is in the range: " prec: 20 (safeAdd a b))
|
||||
)
|
||||
}
|
||||
25
Task/Safe-addition/Wren/safe-addition-1.wren
Normal file
25
Task/Safe-addition/Wren/safe-addition-1.wren
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/* safe_addition.wren */
|
||||
class Interval {
|
||||
construct new(lower, upper) {
|
||||
if (lower.type != Num || upper.type != Num) {
|
||||
Fiber.abort("Arguments must be numbers.")
|
||||
}
|
||||
_lower = lower
|
||||
_upper = upper
|
||||
}
|
||||
|
||||
lower { _lower }
|
||||
upper { _upper }
|
||||
|
||||
static stepAway(x) { new(nextAfter_(x, -1/0), nextAfter_(x, 1/0)) }
|
||||
|
||||
static safeAdd(x, y) { stepAway(x + y) }
|
||||
|
||||
foreign static nextAfter_(x, y) // the code for this is written in C
|
||||
|
||||
toString { "[%(_lower), %(_upper)]" }
|
||||
}
|
||||
|
||||
var a = 1.2
|
||||
var b = 0.03
|
||||
System.print("(%(a) + %(b)) is in the range %(Interval.safeAdd(a,b))")
|
||||
83
Task/Safe-addition/Wren/safe-addition-2.wren
Normal file
83
Task/Safe-addition/Wren/safe-addition-2.wren
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "wren.h"
|
||||
|
||||
void Interval_nextAfter(WrenVM* vm) {
|
||||
double x = wrenGetSlotDouble(vm, 1);
|
||||
double y = wrenGetSlotDouble(vm, 2);
|
||||
wrenSetSlotDouble(vm, 0, nextafter(x, y));
|
||||
}
|
||||
|
||||
WrenForeignMethodFn bindForeignMethod(
|
||||
WrenVM* vm,
|
||||
const char* module,
|
||||
const char* className,
|
||||
bool isStatic,
|
||||
const char* signature) {
|
||||
if (strcmp(module, "main") == 0) {
|
||||
if (strcmp(className, "Interval") == 0) {
|
||||
if (isStatic && strcmp(signature, "nextAfter_(_,_)") == 0) {
|
||||
return Interval_nextAfter;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void writeFn(WrenVM* vm, const char* text) {
|
||||
printf("%s", text);
|
||||
}
|
||||
|
||||
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
|
||||
switch (errorType) {
|
||||
case WREN_ERROR_COMPILE:
|
||||
printf("[%s line %d] [Error] %s\n", module, line, msg);
|
||||
break;
|
||||
case WREN_ERROR_STACK_TRACE:
|
||||
printf("[%s line %d] in %s\n", module, line, msg);
|
||||
break;
|
||||
case WREN_ERROR_RUNTIME:
|
||||
printf("[Runtime Error] %s\n", msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char *readFile(const char *fileName) {
|
||||
FILE *f = fopen(fileName, "r");
|
||||
fseek(f, 0, SEEK_END);
|
||||
long fsize = ftell(f);
|
||||
rewind(f);
|
||||
char *script = malloc(fsize + 1);
|
||||
fread(script, 1, fsize, f);
|
||||
fclose(f);
|
||||
script[fsize] = 0;
|
||||
return script;
|
||||
}
|
||||
|
||||
int main() {
|
||||
WrenConfiguration config;
|
||||
wrenInitConfiguration(&config);
|
||||
config.writeFn = &writeFn;
|
||||
config.errorFn = &errorFn;
|
||||
config.bindForeignMethodFn = &bindForeignMethod;
|
||||
WrenVM* vm = wrenNewVM(&config);
|
||||
const char* module = "main";
|
||||
const char* fileName = "safe_addition.wren";
|
||||
char *script = readFile(fileName);
|
||||
WrenInterpretResult result = wrenInterpret(vm, module, script);
|
||||
switch (result) {
|
||||
case WREN_RESULT_COMPILE_ERROR:
|
||||
printf("Compile Error!\n");
|
||||
break;
|
||||
case WREN_RESULT_RUNTIME_ERROR:
|
||||
printf("Runtime Error!\n");
|
||||
break;
|
||||
case WREN_RESULT_SUCCESS:
|
||||
break;
|
||||
}
|
||||
wrenFreeVM(vm);
|
||||
free(script);
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue