# Map range

Given two ranges:

Map range
You are encouraged to solve this task according to the task description, using any language you may know.
•   ${\displaystyle [a_{1},a_{2}]}$   and
•   ${\displaystyle [b_{1},b_{2}]}$;
•   then a value   ${\displaystyle s}$   in range   ${\displaystyle [a_{1},a_{2}]}$
•   is linearly mapped to a value   ${\displaystyle t}$   in range   ${\displaystyle [b_{1},b_{2}]}$

where:

•   ${\displaystyle t=b_{1}+{(s-a_{1})(b_{2}-b_{1}) \over (a_{2}-a_{1})}}$

Write a function/subroutine/... that takes two ranges and a real number, and returns the mapping of the real number from the first to the second range.

Use this function to map values from the range    [0, 10]    to the range    [-1, 0].

Extra credit

Show additional idiomatic ways of performing the mapping, using tools available to the language.

## 11l

Translation of: Python
F maprange(a, b, s)
R b[0] + (Float(s - a[0]) * (b[1] - b[0]) / (a[1] - a[0]))

L(s) 0..10
print(‘#2 maps to #.’.format(s, maprange((0, 10), (-1, 0), s)))
Output:
 0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0


## 6502 Assembly

A range like [0, n] for some natural number n < 255 can be easily mapped with a lookup table. The second range can be anything, as long as each entry is the same length and are stored consecutively in the desired order. This method requires a bit of compile-time knowledge, but is very efficient in terms of speed. Each element Bn is stored at relative offset An .

mapping:
byte $00,$00,$80,$BF ;-1.0f (stored little-endian so the bytes are backwards)
byte $66,$66,$66,$BF ;-0.9f
byte $CD,$CC,$4C,$BF ;-0.8f
byte $33,$33,$33,$BF ;-0.7f
etc.

If the range isn't [0, n], but begins at some other natural number [k, n] where k,n < 255 , we can express it as [0, n-k] instead and simply subtract the "key" at runtime to get the offset.

This method is very convenient for implementing ASCII into hardware that lacks a built-in system font (like the NES). You can save graphics memory by mapping tile number 0 to ASCII 32, tile number 01 to 33, and so on. Had you mapped them "correctly," (i.e. tile number 32 to ASCII 32) you would still need a "blank tile" as tile number zero. So the easier solution is to subtract 32 from the character code before printing.

;runs during non-maskable interrupt.
PrintChar:
;a = char to print
SEC
SBC #$32 ;subtract ascii offset to map the index to the correct tile graphics data. ;everything below this comment is hardware-specific mumbo-jumbo, feel free to ignore it if you don't care. ;ideally you'd want to do this before getting here so that the only thing that happens during NMI is the write to vram. pha LDA Cursor_Y ASL ASL ASL ASL ASL STA tempY ;row * 32 LDA #$20
STA tempX
LDA $2002 ;reset picture processor high-low latch LDA tempX STA$2006 ;this register is big-endian for some reason. Which is why I had to store Cursor_Y << 5 into tempY rather than here directly.
LDA tempY
STA $2006 PLA STA$2007

## ACL2

(defun mapping (a1 a2 b1 b2 s)
(+ b1 (/ (* (- s a1)
(- b2 b1))
(- a2 a1))))

(defun map-each (a1 a2 b1 b2 ss)
(if (endp ss)
nil
(cons (mapping a1 a2 b1 b2 (first ss))
(map-each a1 a2 b1 b2 (rest ss)))))

(map-each 0 10 -1 0 '(0 1 2 3 4 5 6 7 8 9 10))

;; (-1 -9/10 -4/5 -7/10 -3/5 -1/2 -2/5 -3/10 -1/5 -1/10 0)


## Action!

INCLUDE "D2:REAL.ACT" ;from the Action! Tool Kit

PROC Map(REAL POINTER a1,a2,b1,b2,s,res)
REAL tmp1,tmp2,tmp3

RealSub(s,a1,tmp1) ;tmp1=s-a1
RealSub(b2,b1,tmp2) ;tmp2=b2-b1
RealMult(tmp1,tmp2,tmp3) ;tmp3=(s-a1)*(b2-b1)
RealSub(a2,a1,tmp1) ;tmp1=a2-a1
RealDiv(tmp3,tmp1,tmp2) ;tmp2=(s-a1)*(b2-b1)/(a2-a1)
RETURN

PROC Main()
BYTE i
REAL a1,a2,b1,b2,s,res

Put(125) PutE() ;clear screen

ValR("0",a1) ValR("10",a2)
ValR("-1",b1) ValR("0",b2)

FOR i=0 TO 10
DO
IntToReal(i,s)
Map(a1,a2,b1,b2,s,res)
PrintR(s) Print(" maps to ")
PrintRE(res)
OD
RETURN
Output:
0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0


with Ada.Text_IO;
procedure Map is
type First_Range  is new Float range 0.0 .. 10.0;
type Second_Range is new Float range -1.0 .. 0.0;
function Translate (Value : First_Range) return Second_Range is
B1 : Float := Float (Second_Range'First);
B2 : Float := Float (Second_Range'Last);
A1 : Float := Float (First_Range'First);
A2 : Float := Float (First_Range'Last);
Result : Float;
begin
Result := B1 + (Float (Value) - A1) * (B2 - B1) / (A2 - A1);
return Second_Range (Result);
end;
function Translate (Value : Second_Range) return First_Range is
B1 : Float := Float (First_Range'First);
B2 : Float := Float (First_Range'Last);
A1 : Float := Float (Second_Range'First);
A2 : Float := Float (Second_Range'Last);
Result : Float;
begin
Result := B1 + (Float (Value) - A1) * (B2 - B1) / (A2 - A1);
return First_Range (Result);
end;
Test_Value : First_Range := First_Range'First;
begin
loop
Ada.Text_IO.Put_Line (First_Range'Image (Test_Value) & " maps to: "
& Second_Range'Image (Translate (Test_Value)));
exit when Test_Value = First_Range'Last;
Test_Value := Test_Value + 1.0;
end loop;
end Map;

Output:
 0.00000E+00 maps to: -1.00000E+00
1.00000E+00 maps to: -9.00000E-01
2.00000E+00 maps to: -8.00000E-01
3.00000E+00 maps to: -7.00000E-01
4.00000E+00 maps to: -6.00000E-01
5.00000E+00 maps to: -5.00000E-01
6.00000E+00 maps to: -4.00000E-01
7.00000E+00 maps to: -3.00000E-01
8.00000E+00 maps to: -2.00000E-01
9.00000E+00 maps to: -1.00000E-01
1.00000E+01 maps to:  0.00000E+00

## ALGOL 68

# maps a real s in the range [ a1, a2 ] to the range [ b1, b2 ]           #
# there are no checks that s is in the range or that the ranges are valid #
PROC map range = ( REAL s, a1, a2, b1, b2 )REAL:
b1 + ( ( s - a1 ) * ( b2 - b1 ) ) / ( a2 - a1 );

# test the mapping #
FOR i FROM 0 TO 10 DO
print( ( whole( i, -2 ), " maps to ", fixed( map range( i, 0, 10, -1, 0 ), -8, 2 ), newline ) )
OD
Output:
 0 maps to    -1.00
1 maps to    -0.90
2 maps to    -0.80
3 maps to    -0.70
4 maps to    -0.60
5 maps to    -0.50
6 maps to    -0.40
7 maps to    -0.30
8 maps to    -0.20
9 maps to    -0.10
10 maps to     0.00


## Amazing Hopper

La función "Seqspaced" es una macro-sustitución de "seqsp", y está construida, internamente, como una rutina en C que realiza el siguiente cálculo (en pseudocódigo):

double inc = (nHasta - nDesde) / ( nTotal - 1);
lista[0] = nDesde;
lista[nTotal] = nHasta;
for( n=1; n<nTotal; n++){
lista[n] = lista[n-1] + inc;
}


Macro-sustitución de "Seqspaced":

#defn  Seqspaced(__X__,__Y__,__Z__,_V_)   #ATOM#CMPLX;#ATOM#CMPLX;#ATOM#CMPLX;keep;lthan(1);\
do{{"Seqspaced: num elements < 1"}throw(2301)},seqsp(_V_)

Otras macrosustituciones:

#defn  Toksep(__X__)       #ATOM#CMPLX;toksep;
#defn  Cat(_X_,*)          #ATOM#CMPLX;#GENCODE $$*$$$#ATCMLIST;cat; #ENDGEN #defn Justleft(_X_,_V_) {" "};#ATOM#CMPLX;#ATOM#CMPLX;padright; Código que resuelve la tarea: #include <jambo.h> Main v=0,w=0 Seqspaced(-1,0,11,w) // [-1,0}->[0-10]=11 números Seqspaced(0,10,11,v) Toksep( "\n" ) Cat( Justright(5,Str(v))," => ",Justright(5,Str(w))), Prnl End Output: $ hopper maprange.jambo
0 =>    -1
1 =>  -0.9
2 =>  -0.8
3 =>  -0.7
4 =>  -0.6
5 =>  -0.5
6 =>  -0.4
7 =>  -0.3
8 =>  -0.2
9 =>  -0.1
10 =>     0
& 0:?n
&   whl
' ( !n:~>10
& out$("f(" !n ") = " flt$(mapRange$(0,10.-1,0.!n),2)) & 1+!n:?n ) ); Output: Mapping [0,10] to [-1,0] at intervals of 1: f( 0 ) = -1,00*10E0 f( 1 ) = -9,00*10E-1 f( 2 ) = -8,00*10E-1 f( 3 ) = -7,00*10E-1 f( 4 ) = -6,00*10E-1 f( 5 ) = -5,00*10E-1 f( 6 ) = -4,00*10E-1 f( 7 ) = -3,00*10E-1 f( 8 ) = -2,00*10E-1 f( 9 ) = -1,00*10E-1 f( 10 ) = 0 ## C #include <stdio.h> #define mapRange(a1,a2,b1,b2,s) (b1 + (s-a1)*(b2-b1)/(a2-a1)) int main() { int i; puts("Mapping [0,10] to [-1,0] at intervals of 1:"); for(i=0;i<=10;i++) { printf("f(%d) = %g\n",i,mapRange(0,10,-1,0,i)); } return 0; }  Output: Mapping [0,10] to [-1,0] at intervals of 1: f(0) = -1 f(1) = -0.9 f(2) = -0.8 f(3) = -0.7 f(4) = -0.6 f(5) = -0.5 f(6) = -0.4 f(7) = -0.3 f(8) = -0.2 f(9) = -0.1 f(10) = 0 ## C# using System; using System.Linq; public class MapRange { public static void Main() { foreach (int i in Enumerable.Range(0, 11)) Console.WriteLine($"{i} maps to {Map(0, 10, -1, 0, i)}");
}

static double Map(double a1, double a2, double b1, double b2, double s) => b1 + (s - a1) * (b2 - b1) / (a2 - a1);
}

Output:
0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0

## C++

This example defines a template function to handle the mapping, using two std::pair objects to define the source and destination ranges. It returns the provided value mapped into the target range.

It's not written efficiently; certainly, there can be fewer explicit temporary variables. The use of the template offers a choice in types for precision and accuracy considerations, though one area for improvement might be to allow a different type for intermediate calculations.

#include <iostream>
#include <utility>

template<typename tVal>
tVal map_value(std::pair<tVal,tVal> a, std::pair<tVal, tVal> b, tVal inVal)
{
tVal inValNorm = inVal - a.first;
tVal aUpperNorm = a.second - a.first;
tVal normPosition = inValNorm / aUpperNorm;

tVal bUpperNorm = b.second - b.first;
tVal bValNorm = normPosition * bUpperNorm;
tVal outVal = b.first + bValNorm;

return outVal;
}

int main()
{
std::pair<float,float> a(0,10), b(-1,0);

for(float value = 0.0; 10.0 >= value; ++value)
std::cout << "map_value(" << value << ") = " << map_value(a, b, value) << std::endl;

return 0;
}

Output:
map_value(0) = -1
map_value(1) = -0.9
map_value(2) = -0.8
map_value(3) = -0.7
map_value(4) = -0.6
map_value(5) = -0.5
map_value(6) = -0.4
map_value(7) = -0.3
map_value(8) = -0.2
map_value(9) = -0.1
map_value(10) = 0


## Clojure

Translation of: Python
(defn maprange [[a1 a2] [b1 b2] s]
(+ b1 (/ (* (- s a1) (- b2 b1)) (- a2 a1))))

> (doseq [s (range 11)]
(printf "%2s maps to %s\n" s (maprange [0 10] [-1 0] s)))

0 maps to -1
1 maps to -9/10
2 maps to -4/5
3 maps to -7/10
4 maps to -3/5
5 maps to -1/2
6 maps to -2/5
7 maps to -3/10
8 maps to -1/5
9 maps to -1/10
10 maps to 0


## COBOL

Works with: OpenCOBOL
       IDENTIFICATION DIVISION.
PROGRAM-ID. demo-map-range.

DATA DIVISION.
WORKING-STORAGE SECTION.
01  i                       USAGE FLOAT-LONG.

01  mapped-num              USAGE FLOAT-LONG.

01  a-begin                 USAGE FLOAT-LONG VALUE 0.
01  a-end                   USAGE FLOAT-LONG VALUE 10.

01  b-begin                 USAGE FLOAT-LONG VALUE -1.
01  b-end                   USAGE FLOAT-LONG VALUE 0.

01  i-display               PIC --9.9.
01  mapped-display          PIC --9.9.

PROCEDURE DIVISION.
PERFORM VARYING i FROM 0 BY 1 UNTIL i > 10
CALL "map-range" USING CONTENT a-begin, a-end, b-begin,
b-end, i, REFERENCE mapped-num
COMPUTE i-display ROUNDED = i
COMPUTE mapped-display ROUNDED = mapped-num
DISPLAY FUNCTION TRIM(i-display) " maps to "
FUNCTION TRIM(mapped-display)
END-PERFORM
.
END PROGRAM demo-map-range.

IDENTIFICATION DIVISION.
PROGRAM-ID. map-range.

DATA DIVISION.
01  a-begin                 USAGE FLOAT-LONG.
01  a-end                   USAGE FLOAT-LONG.

01  b-begin                 USAGE FLOAT-LONG.
01  b-end                   USAGE FLOAT-LONG.

01  val-to-map              USAGE FLOAT-LONG.

01  ret                     USAGE FLOAT-LONG.

PROCEDURE DIVISION USING a-begin, a-end, b-begin, b-end,
val-to-map, ret.
COMPUTE ret =
b-begin + ((val-to-map - a-begin) * (b-end - b-begin)
/ (a-end - a-begin))
.
END PROGRAM map-range.


The output is identical to the output of the Common Lisp example.

## CoffeeScript

mapRange = (a1,a2,b1,b2,s) ->
t = b1 + ((s-a1)*(b2 - b1)/(a2-a1))

for s in [0..10]
console.log("#{s} maps to #{mapRange(0,10,-1,0,s)}")

Output:
0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.30000000000000004
8 maps to -0.19999999999999996
9 maps to -0.09999999999999998
10 maps to 0


## Common Lisp

(defun map-range (a1 a2 b1 b2 s)
(+ b1
(/ (* (- s a1)
(- b2 b1))
(- a2 a1))))

(loop
for i from 0 to 10
do (format t "~F maps to ~F~C" i
(map-range 0 10 -1 0 i)
#\Newline))

Output:
0.0 maps to -1.0
1.0 maps to -0.9
2.0 maps to -0.8
3.0 maps to -0.7
4.0 maps to -0.6
5.0 maps to -0.5
6.0 maps to -0.4
7.0 maps to -0.3
8.0 maps to -0.2
9.0 maps to -0.1
10.0 maps to 0.0

## Craft Basic

define a1 = 0, b1 = 0, a2 = 0, b2 = 0

for i = 0 to 10

let s = i
let a1 = 0
let a2 = 10
let b1 = -1
let b2 = 0

print i, " : ", b1 + ( s - a1 ) * ( b2 - b1 ) / ( a2 - a1 )

next i

Output:
0 : -1
1 : -0.9000
2 : -0.8000
3 : -0.7000
4 : -0.6000
5 : -0.5000
6 : -0.4000
7 : -0.3000
8 : -0.2000
9 : -0.1000

10 : 0

## D

double mapRange(in double[] a, in double[] b, in double s)
pure nothrow @nogc {
return b[0] + ((s - a[0]) * (b[1] - b[0]) / (a[1] - a[0]));
}

void main() {
import std.stdio;

immutable r1 = [0.0, 10.0];
immutable r2 = [-1.0, 0.0];
foreach (immutable s; 0 .. 11)
writefln("%2d maps to %5.2f", s, mapRange(r1, r2, s));
}

Output:
 0 maps to -1.00
1 maps to -0.90
2 maps to -0.80
3 maps to -0.70
4 maps to -0.60
5 maps to -0.50
6 maps to -0.40
7 maps to -0.30
8 maps to -0.20
9 maps to -0.10
10 maps to  0.00

See #Pascal.

## EasyLang

func map_range a1 a2 b1 b2 s .
return b1 + (s - a1) * (b2 - b1) / (a2 - a1)
.
for i = 0 to 10
print i & " -> " & map_range 0 10 -1 0 i
.

Output:
0 -> -1
1 -> -0.90
2 -> -0.80
3 -> -0.70
4 -> -0.60
5 -> -0.50
6 -> -0.40
7 -> -0.30
8 -> -0.20
9 -> -0.10
10 -> 0


## EchoLisp

EchoLisp provides several native interpolation functions: smoothstep, s-curve, .. and linear which performs linear interpolation.

(lib 'plot) ;; interpolation functions
(lib 'compile)

;; rational version
(define (q-map-range x xmin xmax ymin ymax) (+ ymin (/ ( * (- x xmin) (- ymax ymin)) (- xmax xmin))))

;; float version
(define (map-range x xmin xmax ymin ymax) (+ ymin (// ( * (- x xmin) (- ymax ymin)) (- xmax xmin))))
; accelerate it
(compile 'map-range "-vf")

(q-map-range 4 0 10 -1 0)
→ -3/5
(map-range 4 0 10 -1 0)
→ -0.6
(linear 4 0 10 -1 0) ;; native
→ -0.6

(for [(x (in-range 0 10))] (writeln x (q-map-range x 0 10 -1 0) (map-range x 0 10 -1 0)))

0     -1     -1
1     -9/10     -0.9
2     -4/5     -0.8
3     -7/10     -0.7
4     -3/5     -0.6
5     -1/2     -0.5
6     -2/5     -0.4
7     -3/10     -0.3
8     -1/5     -0.2
9     -1/10     -0.1


## Elixir

defmodule RC do
def map_range(a1 .. a2, b1 .. b2, s) do
b1 + (s - a1) * (b2 - b1) / (a2 - a1)
end
end

Enum.each(0..10, fn s ->
:io.format "~2w map to ~7.3f~n", [s, RC.map_range(0..10, -1..0, s)]
end)

Output:
 0 map to  -1.000
1 map to  -0.900
2 map to  -0.800
3 map to  -0.700
4 map to  -0.600
5 map to  -0.500
6 map to  -0.400
7 map to  -0.300
8 map to  -0.200
9 map to  -0.100
10 map to   0.000


## Emacs Lisp

(defun maprange (a1 a2 b1 b2 s)
(+ b1 (/ (* (- s a1) (- b2 b1)) (- a2 a1))))

(dotimes (i 10)
(message "%s" (maprange 0.0 10.0 -1.0 0.0 i)))


## Erlang

-module(map_range).
-export([map_value/3]).

map_value({A1,A2},{B1,B2},S) ->
B1 + (S - A1) * (B2 - B1) / (A2 - A1).


## ERRE

PROGRAM RANGE

BEGIN
AL=0   AH=10
BL=-1  BH=0
FOR N=0 TO 10 DO
RANGE=BL+(N-AL)*(BH-BL)/(AH-AL)
WRITE("### maps to ##.##";N;RANGE)
!        PRINT(N;" maps to ";RANGE)
END FOR
END PROGRAM
Output:
  0 maps to -1.00
1 maps to -0.90
2 maps to -0.80
3 maps to -0.70
4 maps to -0.60
5 maps to -0.50
6 maps to -0.40
7 maps to -0.30
8 maps to -0.20
9 maps to -0.10
10 maps to  0.00


## Euphoria

function map_range(sequence a, sequence b, atom s)
return b[1]+(s-a[1])*(b[2]-b[1])/(a[2]-a[1])
end function

for i = 0 to 10 do
printf(1, "%2g maps to %4g\n", {i, map_range({0,10},{-1,0},i)})
end for
Output:
 0 maps to   -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to    0


## F#

let map (a1: float) (a2: float) (b1: float) (b2: float) (s: float): float =
b1 + (s - a1) * (b2 - b1) / (a2 - a1)

let xs = [| for i in 0..10 -> map 0.0 10.0 -1.0 0.0 (float i) |]

for x in xs do printfn "%f" x


## Factor

USE: locals
:: map-range ( a1 a2 b1 b2 x -- y )
x a1 - b2 b1 - * a2 a1 - / b1 + ;


Or:

USING: locals infix ;
:: map-range ( a1 a2 b1 b2 x -- y )
[infix
b1 + (x - a1) * (b2 - b1) / (a2 - a1)
infix] ;


Test run:

10 iota [| x | 0 10 -1 0 x map-range ] map . ! { -1 -9/10 -4/5 -7/10 -3/5 -1/2 -2/5 -3/10 -1/5 -1/10 }


## Fantom

class FRange
{
const Float low
const Float high
// in constructing a range, ensure the low value is smaller than high
new make (Float low, Float high)
{
this.low = ( low <= high ? low : high )
this.high = ( low <= high ? high : low )
}

// return range as a string
override Str toStr () { "[$low,$high]" }

// return a point in given range interpolated into this range
Float remap (Float point, FRange given)
{
this.low + (point - given.low) * (this.high - this.low) / (given.high - given.low)
}
}

class Main
{
public static Void main ()
{
range1 := FRange (0f, 10f)
range2 := FRange (-1f, 0f)
11.times |Int n|
{
m := range2.remap (n.toFloat, range1)
echo ("Value $n in${range1} maps to $m in${range2}")
}
}
}
Output:
Value 0 in [0.0,10.0] maps to -1.0 in [-1.0,0.0]
Value 1 in [0.0,10.0] maps to -0.9 in [-1.0,0.0]
Value 2 in [0.0,10.0] maps to -0.8 in [-1.0,0.0]
Value 3 in [0.0,10.0] maps to -0.7 in [-1.0,0.0]
Value 4 in [0.0,10.0] maps to -0.6 in [-1.0,0.0]
Value 5 in [0.0,10.0] maps to -0.5 in [-1.0,0.0]
Value 6 in [0.0,10.0] maps to -0.4 in [-1.0,0.0]
Value 7 in [0.0,10.0] maps to -0.30000000000000004 in [-1.0,0.0]
Value 8 in [0.0,10.0] maps to -0.19999999999999996 in [-1.0,0.0]
Value 9 in [0.0,10.0] maps to -0.09999999999999998 in [-1.0,0.0]
Value 10 in [0.0,10.0] maps to 0.0 in [-1.0,0.0]


## Forth

\ linear interpolation

: lerp ( b2 b1 a2 a1 s -- t )
fover f-
frot frot f- f/
frot frot fswap fover f- frot f*
f+ ;

: test   11 0 do  0e -1e 10e 0e i s>f lerp f.  loop ;


There is less stack shuffling if you use origin and range instead of endpoints for intervals. (o = a1, r = a2-a1)

: lerp ( o2 r2 r1 o1 s -- t ) fswap f-  fswap f/  f*  f+ ;

: test   11 0 do  -1e 1e 10e 0e i s>f lerp f.  loop ;


## Fortran

Works with: Fortran version 90 and later
program Map
implicit none

real :: t
integer :: i

do i = 0, 10
t = Maprange((/0.0, 10.0/), (/-1.0, 0.0/), real(i))
write(*,*) i, " maps to ", t
end do

contains

function Maprange(a, b, s)
real :: Maprange
real, intent(in) :: a(2), b(2), s

Maprange = (s-a(1)) * (b(2)-b(1)) / (a(2)-a(1)) + b(1)

end function Maprange
end program Map


## FreeBASIC

Translation of: Yabasic
Function MapRange(s As Integer, a1 As Integer, a2 As Integer, b1 As Integer, b2 As Integer) As Double
Return b1+(s-a1)*(b2-b1)/(a2-a1)
End Function

For i As Integer = 0 To 10
Print Using "## maps to ##.#"; i; MapRange(i,0,10,-1,0)
Next i
Sleep

Output:
 0 maps to -1.0
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to  0.0


## Frink

Frink can exactly map to rational numbers so the mapping is round-trippable.

mapRange[s, a1, a2, b1, b2] :=  b1 + (s-a1)(b2-b1)/(a2-a1)

for a = 0 to 10
println["$a\t" + mapRange[a, 0, 10, -1, 0]] Output: 0 -1 1 -9/10 (exactly -0.9) 2 -4/5 (exactly -0.8) 3 -7/10 (exactly -0.7) 4 -3/5 (exactly -0.6) 5 -1/2 (exactly -0.5) 6 -2/5 (exactly -0.4) 7 -3/10 (exactly -0.3) 8 -1/5 (exactly -0.2) 9 -1/10 (exactly -0.1) 10 0  Much more impressive, though, is that Frink is a powerful Computer Algebra System (CAS) and can symbolically invert the function so you can map t back to s: The resulting inverse function is: inverseMapRange[t, a1, a2, b1, b2] := a1 + a1 b1 (-1 b1 + b2)^-1 + -1 a2 b1 (-1 b1 + b2)^-1 + -1 a1 (-1 b1 + b2)^-1 t + a2 (-1 b1 + b2)^-1 t ## FutureBasic include "NSLog.incl" local fn MapRange( s as double, a1 as double, a2 as double, b1 as double, b2 as double ) as double end fn = b1+(s-a1)*(b2-b1)/(a2-a1) NSInteger i for i = 0 to 10 NSLog( @"%2d maps to %5.1f", i, fn MapRange( i, 0, 10, -1, 0 ) ) next HandleEvents Output:  0 maps to -1.0 1 maps to -0.9 2 maps to -0.8 3 maps to -0.7 4 maps to -0.6 5 maps to -0.5 6 maps to -0.4 7 maps to -0.3 8 maps to -0.2 9 maps to -0.1 10 maps to 0.0  ## GDScript func mapRange(s:float, a1:float, a2:float, b1:float, b2:float) -> float : return b1 + ((b2-b1)/(a2-a1))*(s-a1) for i in 11 : print( "%2d %+.1f" % [i,mapRange(i,0.0,10.0,-1.0,0.0)] )  Output:  0 -1.0 1 -0.9 2 -0.8 3 -0.7 4 -0.6 5 -0.5 6 -0.4 7 -0.3 8 -0.2 9 -0.1 10 +0.0  ## Go include "NSLog.incl" local fn MapRange( s as double, a1 as double, a2 as double, b1 as double, b2 as double ) as double end fn = b1+(s-a1)*(b2-b1)/(a2-a1) NSInteger i for i = 0 to 10 NSLog( @"%2d maps to %5.1f", i, fn MapRange( i, 0, 10, -1, 0 ) ) next HandleEvents Output:  0 maps to -1.0 1 maps to -0.9 2 maps to -0.8 3 maps to -0.7 4 maps to -0.6 5 maps to -0.5 6 maps to -0.4 7 maps to -0.3 8 maps to -0.2 9 maps to -0.1 10 maps to 0.0  ## Go Basic task package main import "fmt" type rangeBounds struct { b1, b2 float64 } func mapRange(x, y rangeBounds, n float64) float64 { return y.b1 + (n - x.b1) * (y.b2 - y.b1) / (x.b2 - x.b1) } func main() { r1 := rangeBounds{0, 10} r2 := rangeBounds{-1, 0} for n := float64(0); n <= 10; n += 2 { fmt.Println(n, "maps to", mapRange(r1, r2, n)) } }  Output: 0 maps to -1 2 maps to -0.8 4 maps to -0.6 6 maps to -0.4 8 maps to -0.19999999999999996 10 maps to 0  Extra credit First, a function literal replaces the mapping function specified by the basic task. This allows a simpler parameter signature and also allows things to be precomputed for efficiency. newMapRange checks the direction of the first range and if it is decreasing, reverses both ranges. This simplifies an out-of-range check in the function literal. Also, the slope and intercept of the linear function are computed. This allows the range mapping to use the slope intercept formula which is computationally more efficient that the two point formula. Second, ", ok" is a Go idiom. It takes advantage of Go's multiple return values and multiple assignment to return a success/failure disposition. In the case of this task, the result t is undefined if the input s is out of range. package main import "fmt" type rangeBounds struct { b1, b2 float64 } func newRangeMap(xr, yr rangeBounds) func(float64) (float64, bool) { // normalize direction of ranges so that out-of-range test works if xr.b1 > xr.b2 { xr.b1, xr.b2 = xr.b2, xr.b1 yr.b1, yr.b2 = yr.b2, yr.b1 } // compute slope, intercept m := (yr.b2 - yr.b1) / (xr.b2 - xr.b1) b := yr.b1 - m*xr.b1 // return function literal return func(x float64) (y float64, ok bool) { if x < xr.b1 || x > xr.b2 { return 0, false // out of range } return m*x + b, true } } func main() { rm := newRangeMap(rangeBounds{0, 10}, rangeBounds{-1, 0}) for s := float64(-2); s <= 12; s += 2 { t, ok := rm(s) if ok { fmt.Printf("s: %5.2f t: %5.2f\n", s, t) } else { fmt.Printf("s: %5.2f out of range\n", s) } } }  Output: s: -2.00 out of range s: 0.00 t: -1.00 s: 2.00 t: -0.80 s: 4.00 t: -0.60 s: 6.00 t: -0.40 s: 8.00 t: -0.20 s: 10.00 t: 0.00 s: 12.00 out of range  ## Groovy def mapRange(a1, a2, b1, b2, s) { b1 + ((s - a1) * (b2 - b1)) / (a2 - a1) } (0..10).each { s -> println(s + " in [0, 10] maps to " + mapRange(0, 10, -1, 0, s) + " in [-1, 0].") }  Output: 0 in [0, 10] maps to -1 in [-1, 0]. 1 in [0, 10] maps to -0.9 in [-1, 0]. 2 in [0, 10] maps to -0.8 in [-1, 0]. 3 in [0, 10] maps to -0.7 in [-1, 0]. 4 in [0, 10] maps to -0.6 in [-1, 0]. 5 in [0, 10] maps to -0.5 in [-1, 0]. 6 in [0, 10] maps to -0.4 in [-1, 0]. 7 in [0, 10] maps to -0.3 in [-1, 0]. 8 in [0, 10] maps to -0.2 in [-1, 0]. 9 in [0, 10] maps to -0.1 in [-1, 0]. 10 in [0, 10] maps to 0 in [-1, 0].  ## Haskell Rather than handling only floating point numbers, the mapping function takes any number implementing the Fractional typeclass, which in our example also includes exact Rational numbers. import Data.Ratio import Text.Printf (PrintfType, printf) -- Map a value from the range [a1,a2] to the range [b1,b2]. We don't check -- for empty ranges. mapRange :: Fractional a => (a, a) -> (a, a) -> a -> a mapRange (a1, a2) (b1, b2) s = b1 + (s - a1) * (b2 - b1) / (a2 - a1) main :: IO () main -- Perform the mapping over floating point numbers. = do putStrLn "---------- Floating point ----------" mapM_ (\n -> prtD n . mapRange (0, 10) (-1, 0)$ fromIntegral n) [0 .. 10]
-- Perform the same mapping over exact rationals.
putStrLn "---------- Rationals ----------"
| map(_helper( $a;$b; $factor) ); Example: [range(0;11)] | maprange_array([0,10]; [-1, 0])  ## Julia Works with: Julia version 0.6 function maprange(s, a, b) a₁, a₂ = minimum(a), maximum(a) b₁, b₂ = minimum(b), maximum(b) return b₁ + (s - a₁) * (b₂ - b₁) / (a₂ - a₁) end @show maprange(6, 1:10, -1:0) @show maprange(0:10, 0:10, -1:0)  Output: maprange(6, 1:10, -1:0) = -0.4444444444444444 maprange(0:10, 0:10, -1:0) = -1.0:0.1:0.0 ## K  f:{[a1;a2;b1;b2;s] b1+(s-a1)*(b2-b1)%(a2-a1)} +(a; f[0;10;-1;0]'a:!11) ((0;-1.0) (1;-0.9) (2;-0.8) (3;-0.7) (4;-0.6) (5;-0.5) (6;-0.4) (7;-0.3) (8;-0.2) (9;-0.1) (10;0.0))  ## Kotlin // version 1.0.6 class FloatRange(override val start: Float, override val endInclusive: Float) : ClosedRange<Float> fun mapRange(range1: FloatRange, range2: FloatRange, value: Float): Float { if (value !in range1) throw IllegalArgumentException("value is not within the first range") if (range1.endInclusive == range1.start) throw IllegalArgumentException("first range cannot be single-valued") return range2.start + (value - range1.start) * (range2.endInclusive - range2.start) / (range1.endInclusive - range1.start) } fun main(args: Array<String>) { for (i in 0..10) { val mappedValue = mapRange(FloatRange(0.0f, 10.0f), FloatRange(-1.0f, 0.0f), i.toFloat()) println(String.format("%2d maps to %+4.2f", i, mappedValue)) } }  Output:  0 maps to -1.00 1 maps to -0.90 2 maps to -0.80 3 maps to -0.70 4 maps to -0.60 5 maps to -0.50 6 maps to -0.40 7 maps to -0.30 8 maps to -0.20 9 maps to -0.10 10 maps to +0.00  ## Lambdatalk {def maprange {lambda {:a0 :a1 :b0 :b1 :s} {+ :b0 {/ {* {- :s :a0} {- :b1 :b0}} {- :a1 :a0}}}}} -> maprange {maprange 0 10 -1 0 5} -> -0.5 {S.map {maprange 0 10 -1 0} {S.serie 0 10}} -> 0 maps to -1 1 maps to -0.9 2 maps to -0.8 3 maps to -0.7 4 maps to -0.6 5 maps to -0.5 6 maps to -0.4 7 maps to -0.30000000000000004 8 maps to -0.19999999999999996 9 maps to -0.09999999999999998 10 maps to 0  ## Lasso define map_range( a1, a2, b1, b2, number ) => (decimal(#b1) + (decimal(#number) - decimal(#a1)) * (decimal(#b2) - decimal(#b1)) / (decimal(#a2) - decimal(#a1))) -> asstring(-Precision = 1) with number in generateSeries(1,10) do {^ #number ': ' map_range( 0, 10, -1, 0, #number) '<br />' ^}'  Output: 0: -1.0 1: -0.9 2: -0.8 3: -0.7 4: -0.6 5: -0.5 6: -0.4 7: -0.3 8: -0.2 9: -0.1 10: 0.0 ## Liberty BASIC For i = 0 To 10 Print "f(";i;") maps to ";mapToRange(i, 0, 10, -1, 0) Next i End Function mapToRange(value, inputMin, inputMax, outputMin, outputMax) mapToRange = (((value - inputMin) * (outputMax - outputMin)) / (inputMax - inputMin)) + outputMin End Function Output: f(0) maps to -1 f(1) maps to -0.9 f(2) maps to -0.8 f(3) maps to -0.7 f(4) maps to -0.6 f(5) maps to -0.5 f(6) maps to -0.4 f(7) maps to -0.3 f(8) maps to -0.2 f(9) maps to -0.1 f(10) maps to 0 ## Logo to interpolate :s :a1 :a2 :b1 :b2 output (:s-:a1) / (:a2-:a1) * (:b2-:b1) + :b1 end for [i 0 10] [print interpolate :i 0 10 -1 0] ## Lua function map_range( a1, a2, b1, b2, s ) return b1 + (s-a1)*(b2-b1)/(a2-a1) end for i = 0, 10 do print( string.format( "f(%d) = %f", i, map_range( 0, 10, -1, 0, i ) ) ) end  ## M2000 Interpreter ### Using Class module MapRange { class Map { private: a, b, f public: value (x){ =.b+(x-.a)*.f } class: module Map (.a,a2,.b,b2) { if a2-.a=0 then error "wrong parameters" .f<=(b2-.b)/(a2-.a) } } m1=Map(0,10, -1, 0) for i=0 to 10 Print i," maps to ";m1(i) next } MapRange ### Using Lambda module MapRange { Map=lambda (a,a2,b,b2) -> { if a2-a=0 then error "wrong parameters" f=(b2-b)/(a2-a) =lambda a,b,f (x)->b+(x-a)*f } m1=Map(0,10, -1, 0) for i=0 to 10 Print i," maps to ";m1(i) next } MapRange Same output for both versions Output:  0 maps to -1 1 maps to -0.9 2 maps to -0.8 3 maps to -0.7 4 maps to -0.6 5 maps to -0.5 6 maps to -0.4 7 maps to -0.3 8 maps to -0.2 9 maps to -0.1 10 maps to 0  ## Maple Map:=proc(a1,a2,b1,b2,s); return (b1+((s-a1)*(b2-b1)/(a2-a1))); end proc; for i from 0 to 10 do printf("%a maps to ",i); printf("%a\n",Map(0,10,-1,0,i)); end do; ## Mathematica /Wolfram Language Such a function is already built in Rescale[#,{0,10},{-1,0}]&/@Range[0,10]  Output: {-1., -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.} ## Maxima maprange(a, b, c, d) := buildq([e: ratsimp(('x - a)*(d - c)/(b - a) + c)], lambda([x], e))$

f: maprange(0, 10, -1, 0);


## Nemerle

using System;
using System.Console;

module Maprange
{
Maprange(a : double * double, b : double * double, s : double) : double
{
def (a1, a2) = a; def (b1, b2) = b;

b1 + (((s - a1) * (b2 - b1))/(a2 - a1))
}

Main() : void
{
foreach (i in [0 .. 10])
WriteLine("{0, 2:f0} maps to {1:f1}", i, Maprange((0.0, 10.0), (-1.0, 0.0), i));
}
}


## NetRexx

/* NetRexx */
options replace format comments java crossref savelog symbols nobinary

A    = [  0.0, 10.0 ]
B    = [ -1.0,  0.0 ]
incr = 1.0

say 'Mapping ['A[0]',' A[1]'] to ['B[0]',' B[1]'] in increments of' incr':'
loop sVal = A[0] to A[1] by incr
say '  f('sVal.format(3, 3)') ='  mapRange(A, B, sVal).format(4, 3)
end sVal

return

method mapRange(a = Rexx[], b = Rexx[], s_) public static
return mapRange(a[0], a[1], b[0], b[1], s_)

method mapRange(a1, a2, b1, b2, s_) public static
t_ = b1 + ((s_ - a1) * (b2 - b1) / (a2 - a1))
return t_

Output:
Mapping [0.0, 10.0] to [-1.0, 0.0] in increments of 1.0:
f(  0.000) =   -1.000
f(  1.000) =   -0.900
f(  2.000) =   -0.800
f(  3.000) =   -0.700
f(  4.000) =   -0.600
f(  5.000) =   -0.500
f(  6.000) =   -0.400
f(  7.000) =   -0.300
f(  8.000) =   -0.200
f(  9.000) =   -0.100
f( 10.000) =    0.000


## Nim

Translation of: Python
import strformat

type FloatRange = tuple[s, e: float]

proc mapRange(a, b: FloatRange; s: float): float =
b.s + (s - a.s) * (b.e - b.s) / (a.e - a.s)

for i in 0..10:
let m = mapRange((0.0,10.0), (-1.0, 0.0), float(i))
echo &"{i:>2} maps to {m:4.1f}"

Output:
 0 maps to -1.0
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to  0.0

## Objeck

bundle Default {
class Range {
function : MapRange(a1:Float, a2:Float, b1:Float, b2:Float, s:Float) ~ Float {
return b1 + (s-a1)*(b2-b1)/(a2-a1);
}

function : Main(args : String[]) ~ Nil {
"Mapping [0,10] to [-1,0] at intervals of 1:"->PrintLine();
for(i := 0.0; i <= 10.0; i += 1;) {
IO.Console->Print("f(")->Print(i->As(Int))->Print(") = ")->PrintLine(MapRange(0.0, 10.0, -1.0, 0.0, i));
};
}
}
}
Output:
Mapping [0,10] to [-1,0] at intervals of 1:
f(0) = -1
f(1) = -0.9
f(2) = -0.8
f(3) = -0.7
f(4) = -0.6
f(5) = -0.5
f(6) = -0.4
f(7) = -0.3
f(8) = -0.2
f(9) = -0.1
f(10) = 0


## OCaml

let map_range (a1, a2) (b1, b2) s =
b1 +. ((s -. a1) *. (b2 -. b1) /. (a2 -. a1))

let () =
print_endline "Mapping [0,10] to [-1,0] at intervals of 1:";
for i = 0 to 10 do
Printf.printf "f(%d) = %g\n" i (map_range (0.0, 10.0) (-1.0, 0.0) (float i))
done

Output:
Mapping [0,10] to [-1,0] at intervals of 1:
f(0) = -1
f(1) = -0.9
f(2) = -0.8
f(3) = -0.7
f(4) = -0.6
f(5) = -0.5
f(6) = -0.4
f(7) = -0.3
f(8) = -0.2
f(9) = -0.1
f(10) = 0

If range mapping is used in a heavy computational task we can reduce the number of calculations made using partial application and currying:

let map_range (a1, a2) (b1, b2) =
let v = (b2 -. b1) /. (a2 -. a1) in
function s ->
b1 +. ((s -. a1) *. v)

let () =
print_endline "Mapping [0,10] to [-1,0] at intervals of 1:";
let p = (map_range (0.0, 10.0) (-1.0, 0.0)) in
for i = 0 to 10 do
Printf.printf "f(%d) = %g\n" i (p (float i))
done


## Oforth

: mapRange(p1, p2, s)
s p1 first - p2 second p2 first - * p1 second p1 first - asFloat /
p2 first + ;
Output:
Interval newFromToStep(0, 10, 0.5) map(#[ mapRange([0, 10], [ -1, 0 ])]) println
[-1, -0.95, -0.9, -0.85, -0.8, -0.75, -0.7, -0.65, -0.6, -0.55, -0.5, -0.45, -0.4, -0.35,
-0.3, -0.25, -0.2, -0.15, -0.1, -0.05, 0]


## PARI/GP

Usage (e.g.): map([1,10],[0,5],8.)

map(r1,r2,x)=r2[1]+(x-r1[1])*(r2[2]-r2[1])/(r1[2]-r1[1])

## Pascal

Program Map(output);

function MapRange(fromRange, toRange: array of real; value: real): real;
begin
MapRange := (value-fromRange[0]) * (toRange[1]-toRange[0]) / (fromRange[1]-fromRange[0]) + toRange[0];
end;

var
i: integer;
begin
for i := 0 to 10 do
writeln (i, ' maps to: ', MapRange([0.0, 10.0], [-1.0, 0.0], i):4:2);
end.

Output:
:> ./MapRange
0 maps to: -1.00
1 maps to: -0.90
2 maps to: -0.80
3 maps to: -0.70
4 maps to: -0.60
5 maps to: -0.50
6 maps to: -0.40
7 maps to: -0.30
8 maps to: -0.20
9 maps to: -0.10
10 maps to: 0.00


### improvement doing many calculations

Tested with freepascal_32 2.6.4 .Pushing all data over the stack takes quite a long time. Precaltulating the scalefactor helps too.

Time relation doing 1E7 calculations

Org/ const / tMr

double  : 267/177/107 .. 25/16/10

extended: 363/193/123 .. 30/15/10

Output as above.

Program Map(output);

type
real = double;
tRange = Array [0..1] of real;
tMapRec = record
mrFrom,
mrTo : tRange;
mrScale : real
end;

function InitRange(rfrom,rTo:real):tRange;
begin
InitRange[0] :=rfrom;
InitRange[1] :=rTo;
end;

function InitMapRec(const fromRange, toRange: tRange):tMapRec;
begin
With InitMapRec do
Begin
mrFrom := fromRange;
mrTo   := toRange;
mrScale := (toRange[1]-toRange[0]) / (fromRange[1]-fromRange[0]);
end;
end;

function MapRecRange(const value: real;var MR :tMapRec): real;
begin
with MR do
MapRecRange := (value-mrFrom[0]) * mrScale + mrTo[0];
end;

function MapRange(const value: real;const fromRange, toRange: tRange): real;
begin
MapRange := (value-fromRange[0]) * (toRange[1]-toRange[0]) / (fromRange[1]-fromRange[0]) + toRange[0];
end;

var
value:real;
rFrom,rTo : tRange;
mr : tMapRec;
i: LongInt;

begin
rFrom:= InitRange(  0, 10);
rTo  := InitRange( -1,  0);
mr:= InitMapRec(rFrom,rTo);

for i := 0 to 10 do
Begin
value := i;
writeln (i:4, ' maps to: ', MapRange(value,rFrom, rTo):10:6,
MapRecRange(value,mr):10:6);
end;
end.


## Perl

#!/usr/bin/perl -w
use strict ;

sub mapValue {
my ( $range1 ,$range2 , $number ) = @_ ; return ($range2->[ 0 ] +
(( $number -$range1->[ 0 ] ) * ( $range2->[ 1 ] -$range2->[ 0 ] ) ) / ( $range1->[ -1 ] -$range1->[ 0 ] ) ) ;
}
my @numbers = 0..10 ;
my @interval = ( -1 , 0 ) ;
print "The mapped value for $_ is " . mapValue( \@numbers , \@interval ,$_ ) . " !\n" foreach @numbers ;

Output:
The mapped value for 0 is -1 !
The mapped value for 1 is -0.9 !
The mapped value for 2 is -0.8 !
The mapped value for 3 is -0.7 !
The mapped value for 4 is -0.6 !
The mapped value for 5 is -0.5 !
The mapped value for 6 is -0.4 !
The mapped value for 7 is -0.3 !
The mapped value for 8 is -0.2 !
The mapped value for 9 is -0.1 !
The mapped value for 10 is 0 !


## Phix

with javascript_semantics
function map_range(atom s, a1, a2, b1, b2)
return b1+(s-a1)*(b2-b1)/(a2-a1)
end function

for i=0 to 10 by 2 do
printf(1,"%2d : %g\n",{i,map_range(i,0,10,-1,0)})
end for

Output:
 0 : -1
2 : -0.8
4 : -0.6
6 : -0.4
8 : -0.2
10 : 0


## PicoLisp

(scl 1)

(de mapRange (Val A1 A2 B1 B2)
(+ B1 (*/ (- Val A1) (- B2 B1) (- A2 A1))) )

(for Val (range 0 10.0 1.0)
(prinl
(format (mapRange Val 0 10.0 -1.0 0) *Scl) ) )
Output:
-1.0
-0.9
-0.8
-0.7
-0.6
-0.5
-0.4
-0.3
-0.2
-0.1
0.0

## PL/I

map: procedure options (main); /* 24/11/2011 */
declare (a1, a2, b1, b2) float;
declare d fixed decimal (3,1);

do d = 0 to 10 by 0.9, 10;
put skip edit ( d, ' maps to ', map(0, 10, -1, 0, d) ) (f(5,1), a, f(10,6));
end;

map: procedure (a1, a2, b1, b2, s) returns (float);
declare (a1, a2, b1, b2, s) float;
return (b1 + (s - a1)*(b2 - b1) / (a2 - a1) );
end map;
end map;
Output:
  0.0 maps to  -1.000000
0.9 maps to  -0.910000
1.8 maps to  -0.820000
2.7 maps to  -0.730000
3.6 maps to  -0.640000
4.5 maps to  -0.550000
5.4 maps to  -0.460000
6.3 maps to  -0.370000
7.2 maps to  -0.280000
8.1 maps to  -0.190000
9.0 maps to  -0.100000
9.9 maps to  -0.010000
10.0 maps to   0.000000

## PowerShell

function Group-Range
{
[CmdletBinding()]
[OutputType([PSCustomObject])]
Param
(
[Parameter(Mandatory=$true, Position=0)] [ValidateCount(2,2)] [double[]]$Range1,

[Parameter(Mandatory=$true, Position=1)] [ValidateCount(2,2)] [double[]]$Range2,

[Parameter(Mandatory=$true, ValueFromPipeline=$true,
Position=2)]
[double]
$Map ) Process { foreach ($number in $Map) { [PSCustomObject]@{ Index =$number
Mapping = $Range2[0] + ($number - $Range1[0]) * ($Range2[0] - $Range2[1]) / ($Range1[0] - $Range1[1]) } } } }  0..10 | Group-Range (0,10) (-1,0)  Output: Index Mapping ----- ------- 0 -1 1 -0.9 2 -0.8 3 -0.7 4 -0.6 5 -0.5 6 -0.4 7 -0.3 8 -0.2 9 -0.1 10 0  ## PureBasic Structure RR a.f b.f EndStructure Procedure.f MapRange(*a.RR, *b.RR, s) Protected.f a1, a2, b1, b2 a1=*a\a: a2=*a\b b1=*b\a: b2=*b\b ProcedureReturn b1 + ((s - a1) * (b2 - b1) / (a2 - a1)) EndProcedure ;- Test the function If OpenConsole() Define.RR Range1, Range2 Range1\a=0: Range1\b=10 Range2\a=-1:Range2\b=0 ; For i=0 To 10 PrintN(RSet(Str(i),2)+" maps to "+StrF(MapRange(@Range1, @Range2, i),1)) Next EndIf   0 maps to -1.0 1 maps to -0.9 2 maps to -0.8 3 maps to -0.7 4 maps to -0.6 5 maps to -0.5 6 maps to -0.4 7 maps to -0.3 8 maps to -0.2 9 maps to -0.1 10 maps to 0.0 ## Python >>> def maprange( a, b, s): (a1, a2), (b1, b2) = a, b return b1 + ((s - a1) * (b2 - b1) / (a2 - a1)) >>> for s in range(11): print("%2g maps to %g" % (s, maprange( (0, 10), (-1, 0), s))) 0 maps to -1 1 maps to -0.9 2 maps to -0.8 3 maps to -0.7 4 maps to -0.6 5 maps to -0.5 6 maps to -0.4 7 maps to -0.3 8 maps to -0.2 9 maps to -0.1 10 maps to 0  Because of Pythons strict, dynamic, typing rules for numbers the same function can give answers as fractions: >>> from fractions import Fraction >>> for s in range(11): print("%2g maps to %s" % (s, maprange( (0, 10), (-1, 0), Fraction(s)))) 0 maps to -1 1 maps to -9/10 2 maps to -4/5 3 maps to -7/10 4 maps to -3/5 5 maps to -1/2 6 maps to -2/5 7 maps to -3/10 8 maps to -1/5 9 maps to -1/10 10 maps to 0 >>>  ## Quackery As Quackery does not support reals (or floating point), the function takes the argument s as a decimal string, and returns the result, t as a rational number.  [$ "bigrat.qky" loadfile ] now!

[ do over -
2swap
do over -
unrot
dip [ $->v drop ] n->v v- rot n->v v/ rot n->v v* rot n->v v+ ] is maprange ($ [ [ --> n/d )

$"0 1 2 3 4 5 6 7 8 9 10" nest$
witheach
[ dup echo$say " maps to " ' [ 0 10 ] ' [ -1 0 ] maprange 7 point$ echo$cr ] Output: 0 maps to -1 1 maps to -0.9 2 maps to -0.8 3 maps to -0.7 4 maps to -0.6 5 maps to -0.5 6 maps to -0.4 7 maps to -0.3 8 maps to -0.2 9 maps to -0.1 10 maps to 0 ## R tRange <- function(aRange, bRange, s) { #Guard clauses. We could write some proper error messages, but this is all we really need. stopifnot(length(aRange) == 2, length(bRange) == 2, is.numeric(aRange), is.numeric(bRange), is.numeric(s), s >= aRange[1], s <= aRange[2]) bRange[1] + ((s - aRange[1]) * (bRange[2] - bRange[1])) / (aRange[2] - aRange[1]) } data.frame(s = 0:10, t = sapply(0:10, tRange, aRange = c(0, 10), bRange = c(-1, 0)))  Output:  s t 1 0 -1.0 2 1 -0.9 3 2 -0.8 4 3 -0.7 5 4 -0.6 6 5 -0.5 7 6 -0.4 8 7 -0.3 9 8 -0.2 10 9 -0.1 11 10 0.0 ## Racket #lang racket (define (make-range-map a1 a2 b1 b2) ;; returns a mapping function, doing computing the differences in ;; advance so it's fast (let ([a (- a2 a1)] [b (- b2 b1)]) (λ(s) (exact->inexact (+ b1 (/ (* (- s a1) b) a)))))) (define map (make-range-map 0 10 -1 0)) (for ([i (in-range 0 11)]) (printf "~a --> ~a\n" i (map i)))  Output: 0 --> -1.0 1 --> -0.9 2 --> -0.8 3 --> -0.7 4 --> -0.6 5 --> -0.5 6 --> -0.4 7 --> -0.3 8 --> -0.2 9 --> -0.1 10 --> 0.0  ## Raku (formerly Perl 6) Return a closure that does the mapping without have to supply the ranges every time. sub getmapper(Range$a, Range  $b) { my ($a1, $a2) =$a.bounds;
my ($b1,$b2) = $b.bounds; return ->$s { $b1 + (($s-$a1) * ($b2-$b1) / ($a2-$a1)) } } my &mapper = getmapper(0 .. 10, -1 .. 0); for ^11 ->$x {say "$x maps to &mapper($x)"}

Output:
0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0

## ReScript

let map_range = ((a1, a2), (b1, b2), s) => {
b1 +. ((s -. a1) *. (b2 -. b1) /. (a2 -. a1))
}

Js.log("Mapping [0,10] to [-1,0] at intervals of 1:")

for i in 0 to 10 {
Js.log("f(" ++ Js.String.make(i) ++ ") = " ++
Js.String.make(map_range((0.0, 10.0), (-1.0, 0.0), float(i))))
}
<!DOCTYPE html>
<html>
<title>ReScript: Map_range</title>
<meta charset="UTF-8"/>
<style rel="stylesheet" type="text/css">
body { color:#EEE; background-color:#888; }
</style>
<script>var exports = {};</script>
<script src="./maprange.js"></script>
<body>

</body>
</html>

Output:
Mapping [0,10] to [-1,0] at intervals of 1:
f(0) = -1
f(1) = -0.9
f(2) = -0.8
f(3) = -0.7
f(4) = -0.6
f(5) = -0.5
f(6) = -0.4
f(7) = -0.30000000000000004
f(8) = -0.19999999999999996
f(9) = -0.09999999999999998
f(10) = 0


## REXX

(The first three REXX versions don't differ idiomatically that much, but differ mostly just in style.)

The first three versions support different increments   (the   inc   variable)   and an   A   range that is decreasing in values
(that is, the 2nd number [usually the high] in the range is less than the first number in the range [usually the low]).   Also,
the   BY   (increment)   is automatically adjusted   (either   upwards   or   downwards).   Also, both sets of numbers in the
output are aligned  (vertically).

### version 1

/*REXX program maps and displays a  range of numbers from  one range  to  another range.*/
rangeA =   0   10                                      /*or:   rangeA =   '  0  10 '    */
rangeB =  -1    0                                      /*or:   rangeB =   " -1   0 "    */
parse  var   rangeA  L  H
inc= 1
do j=L  to H  by inc * (1 - 2 * sign(H<L) )  /*BY:   either   +inc  or  -inc  */
say right(j, 9)      ' maps to '      mapR(rangeA, rangeB, j)
end   /*j*/
exit                                                   /*stick a fork in it, we're done.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
mapR: procedure; parse arg a1 a2,b1 b2,s;$=b1+(s-a1)*(b2-b1)/(a2-a1);return left('',$>=0)$ output:  0 maps to -1 1 maps to -0.9 2 maps to -0.8 3 maps to -0.7 4 maps to -0.6 5 maps to -0.5 6 maps to -0.4 7 maps to -0.3 8 maps to -0.2 9 maps to -0.1 10 maps to 0  ### version 2 This version demonstrates an increment (inc) of 1/2 instead of the usual unity. Note that this REXX version also uses a different rangeA numbers (they are reversed). /*REXX program maps and displays a range of numbers from one range to another range.*/ rangeA = 10 0 /*or: rangeA = ' 0 10 ' */ rangeB = -1 0 /*or: rangeB = " -1 0 " */ parse var rangeA L H inc= 1/2 do j=L to H by inc * (1 - 2 * sign(H<L) ) /*BY: either +inc or -inc */ say right(j, 9) ' maps to ' mapR(rangeA, rangeB, j) end /*j*/ exit /*stick a fork in it, we're done.*/ /*──────────────────────────────────────────────────────────────────────────────────────*/ mapR: procedure; parse arg a1 a2,b1 b2,s;$=b1+(s-a1)*(b2-b1)/(a2-a1);return left('',$>=0)$

output:
        0  maps to   0
0.5  maps to  -0.05
1.0  maps to  -0.1
1.5  maps to  -0.15
2.0  maps to  -0.2
2.5  maps to  -0.25
3.0  maps to  -0.3
3.5  maps to  -0.35
4.0  maps to  -0.4
4.5  maps to  -0.45
5.0  maps to  -0.5
5.5  maps to  -0.55
6.0  maps to  -0.6
6.5  maps to  -0.65
7.0  maps to  -0.7
7.5  maps to  -0.75
8.0  maps to  -0.8
8.5  maps to  -0.85
9.0  maps to  -0.9
9.5  maps to  -0.95
10.0  maps to  -1


### version 3

This REXX version used a function that calculates and also displays the range mapping.

/*REXX program maps and displays a  range of numbers from  one range  to  another range.*/
rangeA =   0   10
rangeB =  -1    0
inc = 1
call mapR rangeA, rangeB, inc
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
mapR: procedure;  parse arg a1 a2, b1 b2, inc    /* [↓]  BY  is  either   +inc  or -inc.*/
do s=a1   to a2   by  inc  *  (1  -  2  *  sign(a2 < a1) )
t= b1 + (s-a1) * (b2-b1) / (a2-a1)
say right(s, 9)        ' maps to'          left('', t>=0)      t
end   /*s*/
return                                     /* [↑]  LEFT··· aligns non─negative #'s*/

output   is identical to the 1st REXX version.

### Version 4

/*REXX program maps a number from one range to another range.           */
/* 31.10.2013 Walter Pachl   */
/*                  'translated' from an older version 1 without using Procedure */
do j=0  to 10
say right(j,3)   ' maps to '   mapRange(0,10,-1,0,j)
end
exit
/*──────────────────────────────────MAPRANGE subroutine─────────────────*/
mapRange: return arg(3)+(arg(5)-arg(1))*(arg(4)-arg(3))/(arg(2)-arg(1))
/* Arguments are arg a1,a2,b1,b2,x */

Output:
  0  maps to  -1
1  maps to  -0.9
2  maps to  -0.8
3  maps to  -0.7
4  maps to  -0.6
5  maps to  -0.5
6  maps to  -0.4
7  maps to  -0.3
8  maps to  -0.2
9  maps to  -0.1
10  maps to  0


## Ring

# Project : Map range

decimals(1)
al = 0
ah = 10
bl = -1
bh = 0
for n = 0 to 10
see "" + n + " maps to " + maprange(al, bl, n) + nl
next

func maprange(al, bl, s)
return bl + (s - al) * (bh - bl) / (ah - al)

Output:

0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0


## RPL

Ranges are entered as complex numbers to ease input and shorten code

Works with: Halcyon Calc version 4.2.7
RPL code Comment
 ≪  → ra rb s
≪ rb ra - DUP RE SWAP IM /
s ra RE - * rb RE +
≫ ≫  'MAP' STO

( (a1, a2) (b1, b2) s -- t )
Get (b2 - b1)/(a2 - a1)
Multiply by (s - a1) and add b1


Input:
(0,10) (-1,0) 0 MAP
(0,10) (-1,0) 4 MAP
(0,10) (-1,0) 10 MAP

Output:
3: -1
2: -0.6
1: 0


### Basic RPL code

No specific data structure, no local variable, full stack calculation. Shorter, but less practical in use and difficult to read.

≪ SWAP 3 PICK -
SWAP 5 PICK - *
ROT 4 ROLL - / +
≫ 'MAP' STO

Input:
0 10 -1 0 0 MAP
0 10 -1 0 4 MAP
0 10 -1 0 10 MAP

Output:
3: -1
2: -0.6
1: 0


## Ruby

def map_range(a, b, s)
af, al, bf, bl = a.first, a.last, b.first, b.last
bf + (s - af)*(bl - bf).quo(al - af)
end

(0..10).each{|s| puts "%s maps to %g" % [s, map_range(0..10, -1..0, s)]}


Numeric#quo does floating point division.

Output:
0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to 0


To use rational arithmetic, delete s *= 1.0 and either require 'rational', or use Ruby 1.9 (which has Rational in the core library).

(0..10).each do |s|
puts "%s maps to %s" % [s, map_range(0..10, -1..0, s)]
end

Output:

using rational arithmetic

0 maps to -1/1
1 maps to -9/10
2 maps to -4/5
3 maps to -7/10
4 maps to -3/5
5 maps to -1/2
6 maps to -2/5
7 maps to -3/10
8 maps to -1/5
9 maps to -1/10
10 maps to 0/1


## Rust

use std::ops::{Add, Sub, Mul, Div};

fn map_range<T: Copy>(from_range: (T, T), to_range: (T, T), s: T) -> T
Sub<T, Output=T> +
Mul<T, Output=T> +
Div<T, Output=T>
{
to_range.0 + (s - from_range.0) * (to_range.1 - to_range.0) / (from_range.1 - from_range.0)
}

fn main() {
let input: Vec<f64> = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0];
let result = input.into_iter()
.map(|x| map_range((0.0, 10.0), (-1.0, 0.0), x))
.collect::<Vec<f64>>();
print!("{:?}", result);
}

Output:
[-1, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.30000000000000004, -0.19999999999999996, -0.09999999999999998, 0]


## Scala

def mapRange(a1:Double, a2:Double, b1:Double, b2:Double, x:Double):Double=b1+(x-a1)*(b2-b1)/(a2-a1)

for(i <- 0 to 10)
println("%2d in [0, 10] maps to %5.2f in [-1, 0]".format(i, mapRange(0,10, -1,0, i)))

Output:
 0 in [0, 10] maps to -1,00 in [-1, 0]
1 in [0, 10] maps to -0,90 in [-1, 0]
2 in [0, 10] maps to -0,80 in [-1, 0]
3 in [0, 10] maps to -0,70 in [-1, 0]
4 in [0, 10] maps to -0,60 in [-1, 0]
5 in [0, 10] maps to -0,50 in [-1, 0]
6 in [0, 10] maps to -0,40 in [-1, 0]
7 in [0, 10] maps to -0,30 in [-1, 0]
8 in [0, 10] maps to -0,20 in [-1, 0]
9 in [0, 10] maps to -0,10 in [-1, 0]
10 in [0, 10] maps to  0,00 in [-1, 0]

$include "seed7_05.s7i"; include "float.s7i"; const func float: mapRange (in float: a1, in float: a2, in float: b1, in float: b2, ref float: s) is return b1 + (s-a1)*(b2-b1)/(a2-a1); const proc: main is func local var integer: number is 0; begin writeln("Mapping [0,10] to [-1,0] at intervals of 1:"); for number range 0 to 10 do writeln("f(" <& number <& ") = " <& mapRange(0.0, 10.0, -1.0, 0.0, flt(number)) digits 1); end for; end func; Output: Mapping [0,10] to [-1,0] at intervals of 1: f(0) = -1.0 f(1) = -0.9 f(2) = -0.8 f(3) = -0.7 f(4) = -0.6 f(5) = -0.5 f(6) = -0.4 f(7) = -0.3 f(8) = -0.2 f(9) = -0.1 f(10) = 0.0  ## Sidef func map_range(a, b, x) { var (a1, a2, b1, b2) = (a.bounds, b.bounds); x-a1 * b2-b1 / a2-a1 + b1; } var a = 0..10; var b = -1..0; for x in a { say "#{x} maps to #{map_range(a, b, x)}"; }  Output: 0 maps to -1 1 maps to -0.9 2 maps to -0.8 3 maps to -0.7 4 maps to -0.6 5 maps to -0.5 6 maps to -0.4 7 maps to -0.3 8 maps to -0.2 9 maps to -0.1 10 maps to 0 ## SparForte As a structured script. #!/usr/local/bin/spar pragma annotate( summary, "mapping" ) @( description, "The task is to write a function/subroutine/... that takes" ) @( description, "two ranges and a real number, and returns the mapping of" ) @( description, "the real number from the first to the second range. Use" ) @( description, "this function to map values from the range [0, 10] to the" ) @( description, "range [-1, 0]." ) @( see_also, "http://rosettacode.org/wiki/Map_range" ) @( author, "Ken O. Burtch" ); pragma license( unrestricted ); pragma restriction( no_external_commands ); procedure mapping is type first_range is new float; type second_range is new float; -- Spar doesn't implement ranges so we'll use constants first_range_first : constant first_range := 0.0; first_range_last : constant first_range := 10.0; second_range_first : constant second_range := -1.0; second_range_last : constant second_range := 0.0; function translate (first_range_value : first_range) return second_range is b1 : constant float := float( second_range_first ); b2 : constant float := float( second_range_last ); a1 : constant float := float( first_range_first ); a2 : constant float := float( first_range_last ); result : float; begin result := b1 + (float (first_range_value) - a1) * (b2 - b1) / (a2 - a1); return second_range(result); end translate; function translate_back (second_range_value : second_range) return first_range is b1 : constant float := float (first_range_first); b2 : constant float := float (first_range_last); a1 : constant float := float (second_range_first); a2 : constant float := float (second_range_last); result : float; begin result := b1 + (float (second_range_value) - a1) * (b2 - b1) / (a2 - a1); return first_range (result); end translate_back; test_value : first_range := first_range_first; translated_value : second_range; translated_back_value : first_range; begin loop translated_value := translate( test_value ); translated_back_value := translate_back( translated_value ); ? strings.image(test_value) & " maps to: " & strings.image (translated_value); ? strings.image(translated_value) & " maps back to: " & strings.image (translated_back_value); exit when test_value = first_range_last; test_value := @ + 1.0; end loop; end mapping;  Output: $ spar mapping.sp
0.0 maps to: -1.00000000000000E+00
-1.00000000000000E+00 maps back to:  0.00000000000000E+00
1.00000000000000E+00 maps to: -9.00000000000000E-01
-9.00000000000000E-01 maps back to:  1.00000000000000E+00
2.00000000000000E+00 maps to: -8.00000000000000E-01
-8.00000000000000E-01 maps back to:  2.00000000000000E+00
3.00000000000000E+00 maps to: -7.00000000000000E-01
-7.00000000000000E-01 maps back to:  3.00000000000000E+00
4.00000000000000E+00 maps to: -6.00000000000000E-01
-6.00000000000000E-01 maps back to:  4.00000000000000E+00
5.00000000000000E+00 maps to: -5.00000000000000E-01
-5.00000000000000E-01 maps back to:  5.00000000000000E+00
6.00000000000000E+00 maps to: -4.00000000000000E-01
-4.00000000000000E-01 maps back to:  6.00000000000000E+00
7.00000000000000E+00 maps to: -3.00000000000000E-01
-3.00000000000000E-01 maps back to:  7.00000000000000E+00
8.00000000000000E+00 maps to: -2.00000000000000E-01
-2.00000000000000E-01 maps back to:  8.00000000000000E+00
9.00000000000000E+00 maps to: -1.00000000000000E-01
-1.00000000000000E-01 maps back to:  9.00000000000000E+00
1.00000000000000E+01 maps to:  0.00000000000000E+00
0.00000000000000E+00 maps back to:  1.00000000000000E+01

## Stata

The following program will map a variable to a new variable. It accepts if and in conditions.

program define maprange
version 15.1
syntax varname(numeric) [if] [in], ///
from(numlist min=2 max=2) to(numlist min=2 max=2) ///
GENerate(name) [REPLACE]
tempname a b c d h
sca a'=:word 1 of from''
sca b'=:word 2 of from''
sca c'=:word 1 of to''
sca d'=:word 2 of to''
sca h'=(d'-c')/(b'-a')
cap confirm variable generate'
if "replace'"=="replace" & !_rc {
qui replace generate'=(varlist'-a')*h'+c' if' in'
}
else {
if "replace'"=="replace" {
di in gr "(note: variable generate' not found)"'
}
qui gen generate'=(varlist'-a')*h'+c' if' in'
}
end


Example

clear
set obs 11
gen x=_n-1
maprange x if mod(x,2)==0, gen(y) from(0 10) to(-10 10)
maprange x if mod(x,2)!=0, gen(y) from(0 10) to(-100 100) replace
list


Output

     +----------+
|  x     y |
|----------|
1. |  0   -10 |
2. |  1   -80 |
3. |  2    -6 |
4. |  3   -40 |
5. |  4    -2 |
|----------|
6. |  5     0 |
7. |  6     2 |
8. |  7    40 |
9. |  8     6 |
10. |  9    80 |
|----------|
11. | 10    10 |
+----------+

## Swift

import Foundation

func mapRanges(_ r1: ClosedRange<Double>, _ r2: ClosedRange<Double>, to: Double) -> Double {
let num = (to - r1.lowerBound) * (r2.upperBound - r2.lowerBound)
let denom = r1.upperBound - r1.lowerBound

return r2.lowerBound + num / denom
}

for i in 0...10 {
print(String(format: "%2d maps to %5.2f", i, mapRanges(0...10, -1...0, to: Double(i))))
}

Output:
 0 maps to -1.00
1 maps to -0.90
2 maps to -0.80
3 maps to -0.70
4 maps to -0.60
5 maps to -0.50
6 maps to -0.40
7 maps to -0.30
8 maps to -0.20
9 maps to -0.10
10 maps to  0.00

## Tcl

package require Tcl 8.5
proc rangemap {rangeA rangeB value} {
lassign $rangeA a1 a2 lassign$rangeB b1 b2
expr {$b1 + ($value - $a1)*double($b2 - $b1)/($a2 - $a1)} }  Demonstration (using a curried alias to bind the ranges mapped from and to): interp alias {} demomap {} rangemap {0 10} {-1 0} for {set i 0} {$i <= 10} {incr i} {
puts [format "%2d -> %5.2f" $i [demomap$i]]
}

Output:
 0 -> -1.00
1 -> -0.90
2 -> -0.80
3 -> -0.70
4 -> -0.60
5 -> -0.50
6 -> -0.40
7 -> -0.30
8 -> -0.20
9 -> -0.10
10 ->  0.00


## Ursala

The function f is defined using pattern matching and substitution, taking a pair of pairs of interval endpoints and a number as parameters, and returning a number.

#import flo

f((("a1","a2"),("b1","b2")),"s") = plus("b1",div(minus("s","a1"),minus("a2","a1")))

#cast %eL

test = f* ((0.,10.),(-1.,0.))-* ari11/0. 10.
Output:
<
-1.000000e+00,
-9.000000e-01,
-8.000000e-01,
-7.000000e-01,
-6.000000e-01,
-5.000000e-01,
-4.000000e-01,
-3.000000e-01,
-2.000000e-01,
-1.000000e-01,
0.000000e+00>

A more idiomatic way is to define f as a second order function

f(("a1","a2"),("b1","b2")) "s" = ...

with the same right hand side as above, so that it takes a pair of intervals and returns a function mapping numbers in one interval to numbers in the other.

An even more idiomatic way is to use the standard library function plin, which takes an arbitrarily long list of interval endpoints and returns a piecewise linear interpolation function.

## Vala

double map_range(double s, int a1, int a2, int b1, int b2) {
return b1+(s-a1)*(b2-b1)/(a2-a1);
}

void main() {
for (int s = 0; s < 11; s++){
print("%2d maps to %5.2f\n", s, map_range(s, 0, 10, -1, 0));
}
}

Output:
 0 maps to -1.00
1 maps to -0.90
2 maps to -0.80
3 maps to -0.70
4 maps to -0.60
5 maps to -0.50
6 maps to -0.40
7 maps to -0.30
8 maps to -0.20
9 maps to -0.10
10 maps to  0.00


## WDTE

let mapRange r1 r2 s =>
+
(at r2 0)
(/
(*
(-
s
(at r1 0)
)
(-
(at r2 1)
(at r2 0)
)
)
(-
(at r1 1)
(at r1 0)
)
)
;

let s => import 'stream';
let str => import 'strings';

s.range 10
-> s.map (@ enum v => [v; mapRange [0; 10] [-1; 0] v])
-> s.map (@ print v => str.format '{} -> {}' (at v 0) (at v 1) -- io.writeln io.stdout)
-> s.drain
;
Output:
0 -> -1
1 -> -0.9
2 -> -0.8
3 -> -0.7
4 -> -0.6
5 -> -0.5
6 -> -0.4
7 -> -0.3
8 -> -0.2
9 -> -0.1

## Wren

Library: Wren-fmt
import "./fmt" for Fmt

var mapRange = Fn.new { |a, b, s| b.from + (s - a.from) * (b.to - b.from) / (a.to - a.from) }

var a = 0..10
var b = -1..0
for (s in a) {
var t = mapRange.call(a, b, s)
Fmt.print("$2d maps to$ h", s, t)
}

Output:
 0 maps to -1
1 maps to -0.9
2 maps to -0.8
3 maps to -0.7
4 maps to -0.6
5 maps to -0.5
6 maps to -0.4
7 maps to -0.3
8 maps to -0.2
9 maps to -0.1
10 maps to  0


## XPL0

include c:\cxpl\codes;

func real Map(A1, A2, B1, B2, S);
real A1, A2, B1, B2, S;
return B1 + (S-A1)*(B2-B1)/(A2-A1);

int I;
[for I:= 0 to 10 do
[if I<10 then ChOut(0, ^ );  IntOut(0, I);
RlOut(0, Map(0., 10., -1., 0., float(I)));
CrLf(0);
];
]
Output:
 0   -1.00000
1   -0.90000
2   -0.80000
3   -0.70000
4   -0.60000
5   -0.50000
6   -0.40000
7   -0.30000
8   -0.20000
9   -0.10000
10    0.00000


## Yabasic

sub MapRange(s, a1, a2, b1, b2)
return b1+(s-a1)*(b2-b1)/(a2-a1)
end sub

for i = 0 to 10 step 2
print i, " : ", MapRange(i,0,10,-1,0)
next

## zkl

fcn mapRange([(a1,a2)], [(b1,b2)], s) // a1a2 is List(a1,a2)
{ b1 + ((s - a1) * (b2 - b1) / (a2 - a1)) }

r1:=T(0.0, 10.0); r2:=T(-1.0, 0.0);
foreach s in ([0.0 .. 10]){
"%2d maps to %5.2f".fmt(s,mapRange(r1,r2, s)).println();
}
Output:
 0 maps to -1.00
1 maps to -0.90
2 maps to -0.80
3 maps to -0.70
4 maps to -0.60
5 maps to -0.50
6 maps to -0.40
7 maps to -0.30
8 maps to -0.20
9 maps to -0.10
10 maps to  0.00