CDROM, F2 Reed-Solomon P Q codes in CIRC encoder - cd-rom

I research info about CDROM principies. In standart http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-130.pdf
On page 35(45 in pdf) i see CIRC encoder. And his have Q code, and P codes, who calculated by reed-solomon algoritm.
I try to confirm this and doit some sample audio tracks(audio track not used scramber as data track) one fill with 0x01 pattern, and one with 0xA5(CIRC interlive byte in packet not bits, and i see Q and P in F3 frame). After i reed this sector from CD(directly from Laser out) with logic analyzer, and decrypt by script. I have this data for track with pattern 0x01
S1 01 01 01 01 01 01 01 01 01 01 01 01 e5 6e 4e c5 01 01 01 01 01 01 01 01 01 01 01 01 ff ff ff ff
S2 01 01 01 01 01 01 01 01 01 01 01 01 e5 6e 4e c5 01 01 01 01 01 01 01 01 01 01 01 01 ff ff ff ff
First byte is Subcode sumbol in this sample SYNC_1 and SYNC_2
For track with pattern 0xA5
S1 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 6b bc a5 72 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 ff ff ff ff
S1 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 6b bc a5 72 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 ff ff ff ff
If see on CIRC all right 12-15 bytes its inverted Q parity and 28-32 P parity(First byte its sybcode his add at F3).
But i cant find algoritm for calculation this bytes, my maths skills very bad. I try calculator from cdrecord, his doit another codes, try some another Reed-Solomon emplemetation but i cant get identical code from this sample.
Where i can get worked implementation of this code.

I'm putting what I find in this answer as I make progress, based on the edc_ecc.c web github files. RSL12 is GF(2^8), polynomial x^8 + x^4 + x^3 + x^2 + 1 => hex 11d. All non-zero numbers in the field can be considered as powers of hex 02.
The P generator polynomial in hex is:
(x+01)(x+02)(x+04)(x+08) = 01 x^4 + 0f x^3 + 36 x^2 + 78 x + 40
If you look at the 4 entries for AP[...][31], you see the values 75, 249, 78, 6, these are the decimal logs of hex 0f, 36, 78, 40. Note that AP should be AP[4][28] (not [4][32]), the fix is shown below.
Based on your (now deleted) comment, I "uninverted" Q in the examples you gave in the original question, and using my own RS demo program to calculate the P parities, I now get 00 00 00 00:
01 01 01 01 01 01 01 01 01 01 01 01 1a 91 b1 3a 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00
a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 94 43 5a 8d a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 00 00 00 00
The Q generator polynomial is the same as the P generator polynomial. It's used for RS(28,24), but the parity bytes are in the middle, so conventional encoding needs to be modified as explained below.
AQ[][] is wrong, using AQ[3][], to get Q[3], I get 69 instead of 3a:
01 01 01 01 01 01 01 01 01 01 01 01 -- -- -- 69 01 01 01 01 01 01 01 01 01 01 01 01
In addition, AQ[0] only has 21 bytes defined, AQ[1] only has 22 bytes defined, AQ[2] only has 23 bytes defined, AQ[3] has 24 bytes defined, but they are apparently wrong.
There is a workaround, use 4 erasure decoding with locations 12 through 15 marked as erasures (the xx xx xx xx) to do the Q encoding:
01 01 01 01 01 01 01 01 01 01 01 01 xx xx xx xx 01 01 01 01 01 01 01 01 01 01 01 01
a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 xx xx xx xx a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5
After the 4 erasure correction, the Q parity bytes are encoded:
01 01 01 01 01 01 01 01 01 01 01 01 1a 91 b1 3a 01 01 01 01 01 01 01 01 01 01 01 01
a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 94 43 5a 8d a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5
Using the 4 erasure decoding method, I generated a fixed AQ[][]:
static const unsigned char AQ[4][24] =
{{58,152,173,95,88,43,134,205,143,131,163,75,249,66,151,116,125,184,110,16,58,62,137,113},
{30,214,148,138,112,154,157,96,49,198,189,249,69,47,147,235,156,47,209,183,138,232,205,120},
{162,244,13,171,213,236,71,177,253,162,59,78,243,180,186,34,78,136,130,85,108,115,178,246},
{158,179,101,94,49,140,211,149,137,169,81,6,72,157,122,131,190,116,22,64,68,143,119,22}};
However if you plan on writing a decoder (that fixes erasures and/or errors), then you could use the same method I did of using a 4 erasure decode instead of doing a encode. If I recall correctly, this is how some early DAT (digital audio tape) drives implemented this, as they also had their parity bytes in the middle of data.
AP should be AP[4][28]. P is RS(32,28), 28 bytes of data used to generate 4 bytes of parities. The first 4 values from each row of AP[...][32] should be removed, so it becomes AP[4][28], and encode_L1_P() should be encoding 28 bytes of data (a one line fix as noted below).
static const unsigned char AP[4][28] =
{{249,142,180,197,5,155,153,132,143,244,101,76,102,155,203,104,58,152,173,95,88,43,134,205,143,131,163,75},
{205,252,218,199,202,41,136,106,119,238,193,103,123,242,83,178,30,214,148,138,112,154,157,96,49,198,189,249},
{67,11,131,40,7,41,80,147,151,17,245,253,208,66,228,116,162,244,13,171,213,236,71,177,253,162,59,78},
{148,186,203,11,161,159,138,149,250,107,82,108,161,209,110,64,158,179,101,94,49,140,211,149,137,169,81,6}};
encode_L1_P() needs one line fixed:
static int
encode_L1_P(inout)
unsigned char inout[L1_RAW + L1_Q + L1_P];
{
unsigned char *P;
int i;
P = inout + L1_RAW + L1_Q;
memset(P, 0, L1_P);
for (i = 0; i < L1_RAW + L1_Q; i++) { /* fix (remove + L1_P) */
unsigned char data;
data = inout[i];
if (data != 0) {
unsigned char base = rs_l12_log[data];
P[0] ^= rs_l12_alog[(base+AP[0][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
P[1] ^= rs_l12_alog[(base+AP[1][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
P[2] ^= rs_l12_alog[(base+AP[2][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
P[3] ^= rs_l12_alog[(base+AP[3][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
}
}
return (0);
}
In response to comments. To generate AQ, I used erasure correction to generate 24 sets of parities:
01 00 00 00 00 00 00 00 00 00 00 00 69 60 bf b7 00 00 00 00 00 00 00 00 00 00 00 00
00 01 00 00 00 00 00 00 00 00 00 00 49 f9 fa 4b 00 00 00 00 00 00 00 00 00 00 00 00
...
00 00 00 00 00 00 00 00 00 00 00 00 9e a7 ab 93 00 00 00 00 00 00 00 00 00 00 01 00
00 00 00 00 00 00 00 00 00 00 00 00 1f 3b cf ea 00 00 00 00 00 00 00 00 00 00 00 01
AQ[][ 0] = hex log2{69 60 bf b7} = decimal {058 030 162 158}
AQ[][ 1] = hex log2{49 f9 fa 4b} = decimal {152 214 244 179}
...
AQ[][22] = hex log2{9e a7 ab 93} = decimal {137 205 178 119}
AQ[][23] = hex log2{1f 3b cf ea} = decimal {113 120 246 022}
An alternative method is to use a full length 255 byte codeword all zeroes, except one byte set to 01 at the appropriate position modulo 255, to generate the parities in the standard way, parities = msg * x^4 % generator. This generates parities 16 bytes beyond their target position, so the offset needs to be adjusted by 255-16 = +239 modulo 255 to produce the target parities:
255_byte_message_offset = 28_byte_message_offset + 239 % 255:
msg[239] = 01 => parities = 69 60 bf b7
msg[240] = 01 => parities = 49 f9 fa 4b
...
msg[010] = 01 => parities = 9e a7 ab 93
msg[011] = 01 => parities = 1f 3b cf ea

Related

Google Sheets - Convert UTF-8 Text to "normal character"

I'm looking for a solution to convert strings formatted in UTF-8? (Avr%C3%ACl) to their normal appearance.
It is a list of Names that should be readable:
Shiv%C3%A3z
H%C3%B4nd%C3%AAmon
H%C3%B4nd%C3%AAmon
Rev%C3%A1
%C3%90reamy
F%C3%A5m%C3%A9
Nob%C3%B4
Nosh%C3%AC
With a list of codes i want to replace them with:
...
Ò c3 92 %c3%92
Ó c3 93 %c3%93
Ô c3 94 %c3%94
Õ c3 95 %c3%95
Ö c3 96 %c3%96
× c3 97 %c3%97
Ø c3 98 %c3%98
Ù c3 99 %c3%99
Ú c3 9a %c3%9a
Û c3 9b %c3%9b
Ü c3 9c %c3%9c
...
I found app-spript snippets, and "hardcoded" =substitute() but since there are not only 5 characters to be searched, i dont want to nest 200+ substitutes inside each other.
Any solutions?
EDIT:
I haven't been clear enough. Sorry for that. I need to "translate" the names in their cells one by one. The keyword was the list for the app-script answer i guess. Actually it is a table of contents where A2 ist the link to the charakter page, B2 the Name i have already extraced from A2 and C2, the server, is also extracted.
A2 Formula:
just a link
B2 Formula:
=trim(regexreplace(trim(REGEXREPLACE(A2;"https://www.wowprogress.com/character/eu";""));"/"&C2&"/";""))
C2 Formula:
=trim(REGEXEXTRACT(trim(REGEXREPLACE(A2;"https://www.wowprogress.com/character/eu";""));"([^/?]+)"))
List of Chars:
! 21 %21
" 22 %22
# 23 %23
$ 24 %24
% 25 %25
& 26 %26
27 %27
( 28 %28
) 29 %29
* 2a %2a
#ERROR! 2b %2b
, 2c %2c
- 2d %2d
. 2e %2e
/ 2f %2f
0 30 %30
1 31 %31
2 32 %32
3 33 %33
4 34 %34
5 35 %35
6 36 %36
7 37 %37
8 38 %38
9 39 %39
: 3a %3a
; 3b %3b
< 3c %3c
#ERROR! 3d %3d
> 3e %3e
? 3f %3f
# 40 %40
A 41 %41
B 42 %42
C 43 %43
D 44 %44
E 45 %45
F 46 %46
G 47 %47
H 48 %48
I 49 %49
J 4a %4a
K 4b %4b
L 4c %4c
M 4d %4d
N 4e %4e
O 4f %4f
P 50 %50
Q 51 %51
R 52 %52
S 53 %53
T 54 %54
U 55 %55
V 56 %56
W 57 %57
X 58 %58
Y 59 %59
Z 5a %5a
[ 5b %5b
\ 5c %5c
] 5d %5d
^ 5e %5e
_ 5f %5f
` 60 %60
a 61 %61
b 62 %62
c 63 %63
d 64 %64
e 65 %65
f 66 %66
g 67 %67
h 68 %68
i 69 %69
j 6a %6a
k 6b %6b
l 6c %6c
m 6d %6d
n 6e %6e
o 6f %6f
p 70 %70
q 71 %71
r 72 %72
s 73 %73
t 74 %74
u 75 %75
v 76 %76
w 77 %77
x 78 %78
y 79 %79
z 7a %7a
{ 7b %7b
| 7c %7c
} 7d %7d
~ 7e %7e
¡ c2 a1 %c2%a1
¢ c2 a2 %c2%a2
£ c2 a3 %c2%a3
¤ c2 a4 %c2%a4
¥ c2 a5 %c2%a5
¦ c2 a6 %c2%a6
§ c2 a7 %c2%a7
¨ c2 a8 %c2%a8
© c2 a9 %c2%a9
ª c2 aa %c2%aa
« c2 ab %c2%ab
¬ c2 ac %c2%ac
­ c2 ad %c2%ad
® c2 ae %c2%ae
¯ c2 af %c2%af
° c2 b0 %c2%b0
± c2 b1 %c2%b1
² c2 b2 %c2%b2
³ c2 b3 %c2%b3
´ c2 b4 %c2%b4
µ c2 b5 %c2%b5
¶ c2 b6 %c2%b6
· c2 b7 %c2%b7
¸ c2 b8 %c2%b8
¹ c2 b9 %c2%b9
º c2 ba %c2%ba
» c2 bb %c2%bb
¼ c2 bc %c2%bc
½ c2 bd %c2%bd
¾ c2 be %c2%be
¿ c2 bf %c2%bf
À c3 80 %c3%80
Á c3 81 %c3%81
 c3 82 %c3%82
à c3 83 %c3%83
Ä c3 84 %c3%84
Å c3 85 %c3%85
Æ c3 86 %c3%86
Ç c3 87 %c3%87
È c3 88 %c3%88
É c3 89 %c3%89
Ê c3 8a %c3%8a
Ë c3 8b %c3%8b
Ì c3 8c %c3%8c
Í c3 8d %c3%8d
Î c3 8e %c3%8e
Ï c3 8f %c3%8f
Ð c3 90 %c3%90
Ñ c3 91 %c3%91
Ò c3 92 %c3%92
Ó c3 93 %c3%93
Ô c3 94 %c3%94
Õ c3 95 %c3%95
Ö c3 96 %c3%96
× c3 97 %c3%97
Ø c3 98 %c3%98
Ù c3 99 %c3%99
Ú c3 9a %c3%9a
Û c3 9b %c3%9b
Ü c3 9c %c3%9c
Ý c3 9d %c3%9d
Þ c3 9e %c3%9e
ß c3 9f %c3%9f
à c3 a0 %c3%a0
á c3 a1 %c3%a1
â c3 a2 %c3%a2
ã c3 a3 %c3%a3
ä c3 a4 %c3%a4
å c3 a5 %c3%a5
æ c3 a6 %c3%a6
ç c3 a7 %c3%a7
è c3 a8 %c3%a8
é c3 a9 %c3%a9
ê c3 aa %c3%aa
ë c3 ab %c3%ab
ì c3 ac %c3%ac
í c3 ad %c3%ad
î c3 ae %c3%ae
ï c3 af %c3%af
ð c3 b0 %c3%b0
ñ c3 b1 %c3%b1
ò c3 b2 %c3%b2
ó c3 b3 %c3%b3
ô c3 b4 %c3%b4
õ c3 b5 %c3%b5
ö c3 b6 %c3%b6
÷ c3 b7 %c3%b7
ø c3 b8 %c3%b8
ù c3 b9 %c3%b9
ú c3 ba %c3%ba
û c3 bb %c3%bb
ü c3 bc %c3%bc
ý c3 bd %c3%bd
þ c3 be %c3%be
ÿ c3 bf %c3%bf
Without any substitute, try
function myFunction(){
var txt = `Shiv%C3%A3z
H%C3%B4nd%C3%AAmon
H%C3%B4nd%C3%AAmon
Rev%C3%A1
%C3%90reamy
F%C3%A5m%C3%A9
Nob%C3%B4
Nosh%C3%AC`
console.log(utf8decode(unescape(txt)))
}
and add this function
function utf8decode(utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
var txt = `Shiv%C3%A3z
H%C3%B4nd%C3%AAmon
H%C3%B4nd%C3%AAmon
Rev%C3%A1
%C3%90reamy
F%C3%A5m%C3%A9
Nob%C3%B4
Nosh%C3%AC`
console.log(utf8decode(unescape(txt)))
function utf8decode(utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
based on gitbub
if you change your mind with SUBSTITUTE brute force:
={""; INDEX("=INDEX(IFERROR("&REPT("SUBSTITUTE(", COUNTA(E2:E))&"A:A, "&QUERY("D"&
SEQUENCE(COUNTA(D2:D), 1, ROW(D2))&", "&"E"&
SEQUENCE(COUNTA(D2:D), 1, ROW(D2))&"),",,9^9)&" ))")}
spreadsheet demo

how to run formula for a range (like a loop) and sum the results?

In google sheets, I am using a formula like this:
=SUM(
VLOOKUP(D2,I2:J8,2,FALSE) * E2,
VLOOKUP(D3,I2:J8,2,FALSE) * E3,
VLOOKUP(D4,I2:J8,2,FALSE) * E4,
VLOOKUP(D5,I2:J8,2,FALSE) * E5,
VLOOKUP(D6,I2:J8,2,FALSE) * E6
)
How to write it as a range? like
=SUM(VLOOKUP(x,I2:J8,2,FALSE) * y)
x is D2 to D6
y is E2 to E6
Try this:
=arrayformula(SUM(VLOOKUP(D2:D6,I2:J8,2,FALSE)*E2:E6))

Different YouTube URLs points to the same video

I found some bug in youtube when I reverse engineering it's video id generator. If I change last characther of the video id, it redirects to same video. How is this possible?
Example:
https://www.youtube.com/watch?v=9bZkp7q19f0
https://www.youtube.com/watch?v=9bZkp7q19f1
https://www.youtube.com/watch?v=9bZkp7q19f2
https://www.youtube.com/watch?v=9bZkp7q19f3
But this url isn't work:
https://www.youtube.com/watch?v=9bZkp7q19f4
The videoId is 8 Bytes (64 bit) base64 encoded. From this post :
For the videoId, it is an 8-byte (64-bit) integer. Applying
Base64-encoding to 8 bytes of data requires 11 characters. However,
since each Base64 character conveys exactly 6 bits, this allocation
could actually hold up to 11 × 6 = 66 bits--a surplus of 2 bits over
what our payload needs. The excess bits are set to zero, which has the
effect of excluding certain characters from ever appearing in the last
position of the encoded string. In particular, the videoId will always
end with one of the following: { A, E, I, M, Q, U, Y, c, g, k, o, s,
w, 0, 4, 8 }
In your case, your videoId is 9bZkp7q19f0 :
enc. | 9 b Z k p 7 q 1 9 f | 0
value | 61 27 25 36 41 59 42 53 61 31 | 52
bin. | 111101 011011 011001 100100 101001 111011 101010 110101 111101 011111 | 1101 00
If you modify the last character, the 64 bit id will change if the 4 most significative bit (MSB) are modified :
9bZkp7q19f1 :
enc. | 9 b Z k p 7 q 1 9 f | 1
value | 61 27 25 36 41 59 42 53 61 31 | 53
bin. | 111101 011011 011001 100100 101001 111011 101010 110101 111101 011111 | 1101 01
9bZkp7q19f2 :
enc. | 9 b Z k p 7 q 1 9 f | 2
value | 61 27 25 36 41 59 42 53 61 31 | 54
bin. | 111101 011011 011001 100100 101001 111011 101010 110101 111101 011111 | 1101 10
9bZkp7q19f3 :
enc. | 9 b Z k p 7 q 1 9 f | 3
value | 61 27 25 36 41 59 42 53 61 31 | 55
bin. | 111101 011011 011001 100100 101001 111011 101010 110101 111101 011111 | 1101 11
This will give a different video id (note the 4 MSB of the last Byte are modified 1101 to 1110) :
enc. | 9 b Z k p 7 q 1 9 f | 4
value | 61 27 25 36 41 59 42 53 61 31 | 56
bin. | 111101 011011 011001 100100 101001 111011 101010 110101 111101 011111 | 1110 00
9bZkp7q19f4 will give a different 64 bit id. Note that if such an id exists 9bZkp7q19f4, 9bZkp7q19f5, 9bZkp7q19f6 and 9bZkp7q19f7 will give the same id.
You can check the base64 encoding/values here

Split huge F# file with mutually recursive functions

In F# I have a very long code file like
let rec f1 a1 a2 a3 a4 a5 .. aN =
...
and f2 a1 a2 a3 a4 a5 ... aN =
...
and f3 a1 a2 a3 a4 a5 ... aN =
...
and f40 a1 a2 a3 a4 a5 ... aN =
...
In other words there are many mutually recursive functions, each with a lot of parameters.
Now the problem is that the file is 17000 lines long, and Visual Studio has become too slow. (For example, I can't hover the mouse over an item to see its type; if I press the dot, there is no completion, and so on)
Therefore I need to split the file into many smaller files. But I can't see a mechanical and easy way to do it.
Could you please give me an advice? I would like a mechanical way to split the code into multiple files, which does not involve writing the type of all functions (preserve type inference).
In the meantime I found a solution (tested):
This is the initial situation (simplified to only have four functions, but in reality they are many more):
let rec f1 a b c =
f2 a b c;
f3 a b c;
f4 a b c;
and f2 a b c =
f1 a b c;
f3 a b c
f4 a b c
and f3 a b c =
f1 a b c;
f2 a b c
f4 a b c
and f4 a b c =
f1 a b c;
f2 a b c
f3 a b c
And here is the solution:
Suppose you decide to move f3 to another file. Then you can split the file above in two files as follows:
FILE 1
======
let callRef mf =
match !mf with
| None -> failwith "function ref is none"
| Some f -> f
let r_f3 = ref None;
let rec f1 a1 a2 a3 =
f2 a b c;
callRef r_f3 a1 b1 c1;
f4 a1 b1 c1;
and f2 a1 a2 a3 =
f1 a b c;
callRef r_f3 a1 b1 c1;
f4 a1 b1 c1;
and f4 a1 a2 a3 =
f1 a b c;
f2 a1 b1 c1;
callRef r_f3 a1 b1 c1;
FILE 2
======
let f3 a1 a2 a3 =
f1 a b c;
f2 a1 b1 c1;
f4 an bn cn;
Then, in the main initialization function (which is in a third file), you need to do
r_f3 := Some f3;
And that's it.
Repeat the same strategy to move f1, f2 and f4 out of the first file.
Update: This solution works well for functions which return unit, but unfortunately for functions which return an actual type it forces you to specify the function type explicitely, e.g.
let (r_f3 : (t1 -> t2 -> t3 -> t4 -> t5) option ref) = ref None;
or you can do this:
let (r_f3 : 'a option ref) = ref None;
but you'll get a compiler warning.

F# beginner using let on multiple dependent names

I hate to ask such a noob question, but I have hunted high and low online--and this is literally my first day.
The following VBA excerpt assigns two variables, where the first variable feeds into the second variable (this code is from www.spreadsheetadvice.com):
If zabs <= 12.7 Then
...
If zabs <= 1.28 Then
Temp = y + a3 - a4 / (y + a5 + a6 / (y + a7))
Q = a0 - zabs * (a1 - a2 * y / Temp)
Else
Temp = (zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11))))
Q = pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / Temp)))
End If
Else ...
I'm trying to replicate it in F#--without using mutables. This works:
let Temp =
if zabs <= 1.28 then
y + a3 - a4 / (y + a5 + a6 / (y + a7))
elif zabs <= 12.7 then
(zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11))))
else
0.0
let Q =
if zabs <= 1.28 then
a0 - zabs * (a1 - a2 * y / Temp)
elif zabs <= 12.7 then
pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / Temp)))
else
0.0
But I don't like separating the two related variables--or repeating the If statements. This doesn't work but is as close as I've come:
let Temp, Q =
if zabs <= 1.28 then
y + a3 - a4 / (y + a5 + a6 / (y + a7)),
a0 - zabs * (a1 - a2 * y / Temp)
elif zabs <= 12.7 then
(zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11)))),
pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / Temp)))
else
0.0,
0.0
It took me a while to figure out the commas on the 3rd, 6th, and 9th lines (if they are in fact right). But the compiler thinks I am trying to use Temp before it is assigned. I assume, or hope, I'm just missing a simple idiom.
This works:
let Temp, Q =
if zabs <= 1.28 then
let temp = y + a3 - a4 / (y + a5 + a6 / (y + a7))
let q = a0 - zabs * (a1 - a2 * y / temp)
temp, q
elif zabs <= 12.7 then
let temp = (zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11))))
let q = pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / temp)))
temp, q
else
0.0, 0.0
It took me a while to figure out the commas on the 3rd, 6th, and 9th lines (if they are in fact right). But the compiler thinks I am trying to use Temp before it is assigned. I assume, or hope, I'm just missing a simple idiom.
Yes, you are missing the basics of the language, you must put the commas because you declare a tuple so you have to bind a value of type 'a * 'b
I suggest to use pattern matching, one of the more powerful thing of F# (and other functional languages) - https://msdn.microsoft.com/en-us/library/dd547125.aspx
let yourfunc zabs =
match zabs with
| x when x <= 1.28 -> let temp = y + a3 - a4 / (y + a5 + a6 / (y + a7))
let q = a0 - zabs * (a1 - a2 * y / temp)
temp, q
| x when x <= 12.7 -> let temp = (zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11))))
let q = pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / temp)))
temp, q
| _ -> 0.0,0.0
I think I was making a simple mistake: because Temp is temporary and subordinate to Q, then Temp should be declared with a scope local to the declaration of Q, not with equal scope as Q. With that figured out, I think using If and using Match work equally well. But Match is probably more idiomatic (thanks Alessandro). Thusly:
let Q =
match zabs with
| i when i <= 1.28 ->
let Temp = y + a3 - a4 / (y + a5 + a6 / (y + a7))
a0 - zabs * (a1 - a2 * y / Temp)
| i when i <= 12.7 ->
let Temp = (zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11))))
pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / Temp)))
| _ ->
0.0
So now I'm bound to want to make two declarations that do need to be of the same scope some time soon and come back to a similar situation again...

Resources