How to construct an APNS notification in RPGLE? - ios

Good Afternoon,
I am attempting to create a socket program which connects to Apple Push Notification Service (APNS) and sends a push notification.
I am wondering if anyone can help me with the actual writing of the APNS notification.
Below you can see my program which I used Scott Klement's Socket Programming tutorial to help me with.
The code that is probably relevant to all of this is marked as 'APNS Notification Format Begin', 'Initialize', and 'Formulate message to APNS' in comments although I included the entire program for reference.
I have read the Provider Requirements on Apple's site Provider Requirements but I am still having trouble getting everything working.
My program compiles and when I debug it / run through the steps I get past establishing an actual connection so I 'think' that this part is OK.
What I am hoping is to get back an error identifier from Apple in the variable errid within the item3 data structure. Apple states in the Provider Requirements that they return a status code if there is an error but that particular variable remains at 1077952576
There are also quite a few other things that I am unsure of
1) I have been given the device token as a Base64 string. The string is 40 some odd characters long but from what I understand, Apple states device token length should be 32 bytes. In RPGLE doesn't 1 character represent 1 byte? If that's the case then I couldn't just declare my variable token as
D token 32a
because it would get cut off?
2) Is anyone able to tell me what I am doing wrong when it comes back to receiving a proper error identifier from Apple in my variable errid?
Any help would be greatly appreciated
H DFTACTGRP(*NO) BNDDIR('QC2LE')
D/copy socket_h
D/copy gskssl_h
*==============================================================*
* APNS Notification Format Begin
*==============================================================*
D request s 1000a varying
D framehdr ds
D command 3I 0 inz(2)
D framelen 10I 0
D framedta s 500a varying
D item1 ds
D itemid1 3I 0 inz(1)
D itemlen1 5I 0 inz(%size(token))
D token 64a
D item2 ds
D itemid2 3I 0 inz(2)
D itemlen2 5I 0
D payload 100a varying
D item3 ds
D itemid3 3I 0 inz(3)
D itemlen3 5I 0 inz(%size(errid))
D errid 10I 0
D item4 ds
D itemid4 3I 0 inz(4)
D itemlen4 5I 0 inz(%size(expire))
D expire 10I 0 inz(0)
D item5 ds
D itemid5 3I 0 inz(5)
D itemlen5 5I 0 inz(%size(priority))
D priority 10I 0 inz(10)
*==============================================================*
* APNS Notification Format End
*==============================================================*
D gsk_strerror PR * extproc('gsk_strerror')
D gsk_ret_value 10I 0 value
D CreateEnv PR like(gsk_handle)
D ConnSock PR 10I 0
d host 256A const
D port 10I 0 value
D UpgradeSock PR like(gsk_handle)
D SslEnv like(gsk_handle) value
D sock 10I 0 value
D CloseSsl PR
D Handle like(gsk_handle) value
D CloseSslEnv PR
D SslEnv like(gsk_handle) value
D ReportError PR
D EscapeMsg PR
D errMsg s 80A varying
D CRLF c x'0d25'
D env s like(gsk_handle)
D s s 10I 0
D connto ds likeds(sockaddr_in)
D SslSock s like(gsk_handle)
D cmd s 400A
D len s 10I 0
D bytesSent s 10I 0
D Reply s 1000A
D bytesRead s 10I 0
D left s 10I 0
D buf s *
D received s 10I 0
D dataPos s 10I 0
D wait s 1A
D rc s 10I 0
/free
// Initialize
token = 'MyDevToken';
payload = '{"aps":{"alert":"You have mail"}}';
itemlen1 = %len(payload);
framedta = item1 + item2 + item3 + item4 + item5;
framelen = %len(framedta);
request = framehdr + framedta;
// Create SSL Environment
env = CreateEnv();
If (env = *NULL);
EscapeMsg();
Endif;
// Connect a socket to an SSL server (using normal socket calls)
// NOTE: Sandbox is the development environment
s = ConnSock('gateway.sandbox.push.apple.com': 2195);
// Upgrade the socket to SSL
SSLSock = UpgradeSock(env: s);
If (SSLSock = *NULL);
EscapeMsg();
Endif;
// **** Formulate message to APNS ******
len = %len(%trimr(request));
callp gsk_secure_soc_write(SSLSock
: %addr(request)
: len
: bytesSent);
// Close everything and end the program
CloseSsl(SslSock);
CloseSslEnv(Env);
*inlr = *on;
/end-free
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* CreateEnv(): Create an SSL environment for client sockets
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P CreateEnv B
D CreateEnv PI like(gsk_handle)
D rc s 10I 0
D SslEnv s like(Gsk_handle)
/free
// Create an SSL environment with default values:
rc = gsk_environment_open(SslEnv);
If (rc <> GSK_OK);
errMsg = %str(gsk_strerror(rc));
return *NULL;
Endif;
// Instruct environment to use the *SYSTEM certificate store
rc = gsk_attribute_set_buffer( SslEnv
: GSK_OS400_APPLICATION_ID
: 'SUMITOMO_APNS_PUSH'
:0 );
If (rc<>GSK_OK);
errMsg = %str(gsk_strerror(rc));
gsk_environment_close( SslEnv );
return *NULL;
Endif;
//Tell the environment that this is a client connection
rc = gsk_attribute_set_enum( SslEnv
: GSK_SESSION_TYPE
: GSK_CLIENT_SESSION );
If (rc <> GSK_OK);
errMsg = %str(gsk_strerror(rc));
gsk_environment_close( SslEnv );
return *NULL;
Endif;
// Activate the new environment
rc = gsk_environment_init( SslEnv );
If (rc <> GSK_OK);
errMsg = %str(gsk_strerror(rc));
gsk_environment_close( SslEnv );
return *NULL;
Endif;
return SslEnv;
/end-free
P E
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* ConnSock(): Create a TCP Socket and connect to a host
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P ConnSock B
D ConnSock PI 10I 0
d host 256A const
D port 10I 0 value
D s s 10I 0
D addr s 10U 0
/free
// look up host
addr = inet_addr(%trim(host));
If (addr = INADDR_NONE);
p_hostent = gethostbyname(%trim(host));
If (p_hostent = *NULL);
errMsg = 'Host not found!';
EscapeMsg();
Endif;
addr = h_addr;
Endif;
// Create a socket
s = socket(AF_INET: SOCK_STREAM: IPPROTO_IP);
If (s < 0);
ReportError();
Endif;
// connect to the host
connto = *ALLx'00';
connto.sin_family = AF_INET;
connto.sin_addr = addr;
connto.sin_port = port;
If (connect(s: %addr(Connto): %size(connto)) = -1);
callp close(S);
ReportError();
Endif;
return s;
/end-free
P E
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* UpgradeSock(): Upgrade a socket to use SSL
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P UpgradeSock B
D UpgradeSock PI like(gsk_handle)
D SslEnv like(gsk_handle) value
D sock 10I 0 value
D Handle s like(Gsk_handle)
/free
rc = gsk_secure_soc_open(SslEnv: Handle);
If (rc <> GSK_OK);
errMsg = %str(gsk_strerror(rc));
return *NULL;
Endif;
rc = gsk_attribute_set_numeric_value(Handle
: GSK_HANDSHAKE_TIMEOUT
: 30 );
If (rc <> GSK_OK);
errMsg = %str(gsk_strerror(rc));
gsk_secure_soc_close(Handle);
return *NULL;
Endif;
rc = gsk_secure_soc_init( Handle );
If (rc <> GSK_OK);
errMsg = %str(gsk_strerror(rc));
gsk_secure_soc_close(Handle);
return *NULL;
Endif;
return Handle;
/end-free
P E
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* CloseSsl(): Close an SSL socket
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P CloseSsl B
D CloseSsl PI
D Handle like(gsk_handle) value
/free
gsk_secure_Soc_close( handle);
/end-free
P E
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* CloseSslEnv(): Close SSL Environment
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P CloseSslEnv B
D CloseSslEnv PI
D SslEnv like(gsk_handle) value
/free
gsk_environment_close( SslEnv );
/end-free
P E
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* EscapeMsg(): Send an escape message w/reason for SSL failure
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P EscapeMsg B
D EscapeMsg PI
D SndPgmMsg PR ExtPgm('QMHSNDPM')
D MessageID 7A Const
D QualMsgF 20A Const
D MsgData 256A Const
D MsgDtaLen 10I 0 Const
D MsgType 10A Const
D CallStkEnt 10A Const
D CallStkCnt 10I 0 Const
D MessageKey 4A
D ErrorCode 1A
D ErrorCode DS
D BytesProv 10I 0 inz(0)
D BytesAvail 10I 0 inz(0)
D wwTheKey S 4A
/free
SndPgmMsg( 'CPF9897'
: 'QCPFMSG *LIBL'
: errMsg
: %len(%trimr(errMsg))
: '*ESCAPE'
: '*CTLBDY'
: 1
: wwTheKey
: ErrorCode );
/end-free
P E
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* ReportError(): Send an escape message explaining any errors
* that occurred.
*
* This function requires binding directory QC2LE in order
* to access the __errno() function.
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P ReportError B
D ReportError PI
D get_errno PR * ExtProc('__errno')
D ptrToErrno s *
D errno s 10I 0 based(ptrToErrno)
D QMHSNDPM PR ExtPgm('QMHSNDPM')
D MessageID 7A Const
D QualMsgF 20A Const
D MsgData 1A Const
D MsgDtaLen 10I 0 Const
D MsgType 10A Const
D CallStkEnt 10A Const
D CallStkCnt 10I 0 Const
D MessageKey 4A
D ErrorCode 8192A options(*varsize)
D ErrorCode DS qualified
D BytesProv 1 4I 0 inz(0)
D BytesAvail 5 8I 0 inz(0)
D MsgKey S 4A
D MsgID s 7A
/free
ptrToErrno = get_errno();
MsgID = 'CPE' + %char(errno);
QMHSNDPM( MsgID
: 'QCPFMSG *LIBL'
: ' '
: 0
: '*ESCAPE'
: '*PGMBDY'
: 1
: MsgKey
: ErrorCode );
/end-free
P E

This isn't even close, you're using characters instead of binary data.
cmd = '2' + 3 + 1 + 64 + 'x' + 2 + 50 + '{"aps":{"alert":"You have mail"}} +
3 + 3 + '001'
This should be closer; but it is off the top of my head and completely untested...
d request s 1000a varying
d frame_hdr ds
d cmd 1a inz(x'02')
d frame_len 10i 0
d frame_data s 500a varying
d device_item ds
d 1a inz(x'01')
d 5i 0 inz(%size(device_item))
d token 32a
d item_hdr ds
d id 1a inz(x'02')
d item_len 5i 0
d item_data s 100a varying
item_data = '{"aps":{"alert":"You have mail"}}';
item_len = %len(item_data);
token = myDevID;
frame_data = device_item + item_hdr + item_data;
frame_len = %len(frame_data);
request = frame_hdr + frame_data;
callp gsk_secure_soc_write(SSLSock
: %addr(request:*DATA)
: %len(request)
: bytesSent);
I've not done raw sockets on the IBM i before, you may have to convert EBCDIC to ASCII. I don't think you'll need to worry about little vs. big endian.
RPG is probably not the best choice for this, Java might be a better choice given the existence of projects like Java PNS
Stackoverflow doesn't have a whole lot of RPG / IBM i traffic. You may get a better response on the following:
http://lists.midrange.com/mailman/listinfo/rpg400-l
http://lists.midrange.com/mailman/listinfo/web400
http://www.scottklement.com/mailman/listinfo/ftpapi

Related

Rearranging equation with division using Maxima

I'm trying to rearrange equation using maxima, but coefmatrix function does not work well with equation that has some division such as RL_parallel
I am getting all zeroes for the coefficients
RL_series: Rs + %i*w*Ls;
RL_parallel: ratsimp( 1 / [1/Rp + 1/(%i*w*Lp)] );
display2d : false $
eq : RL_series = RL_parallel $
vars : [Rs, Rp, Ls, Lp] $
coeffs : coefmatrix ([eq], vars);
coeffs . vars;
The main problem here is that the equation isn't linear in the variables specified, so extracting a coefficient matrix doesn't make any sense, unfortunately.
I am guessing that you want to solve the equation for vars. It seems to me that you'll need additional data, but it could well be that I'm missing something.
Here's what I get. Note that [ ... ] is a list; use ( ... ) for grouping expressions.
(%i1) RL_series: Rs + %i*w*Ls;
(%o1) %i Ls w + Rs
(%i2) RL_parallel: ratsimp( 1 / (1/Rp + 1/(%i*w*Lp)) );
Lp Rp w
(%o2) ------------
Lp w - %i Rp
(%i3) eq : RL_series = RL_parallel;
Lp Rp w
(%o3) %i Ls w + Rs = ------------
Lp w - %i Rp
(%i4) vars : [Rs, Rp, Ls, Lp];
(%o4) [Rs, Rp, Ls, Lp]
(%i5) denom(rhs(eq)) * eq;
(%o5) (Lp w - %i Rp) (%i Ls w + Rs) = Lp Rp w
(%i6) expand (%);
2
(%o6) %i Lp Ls w + Lp Rs w + Ls Rp w - %i Rp Rs = Lp Rp w
Assuming that vars are real, we can separate the real and imaginary parts of the equation.
(%i7) [realpart(%), imagpart(%)];
2
(%o7) [Lp Rs w + Ls Rp w = Lp Rp w, Lp Ls w - Rp Rs = 0]
(%i8) first(%) / (Lp*Rp*w);
Lp Rs w + Ls Rp w
(%o8) ----------------- = 1
Lp Rp w
(%i9) expand (%);
Rs Ls
(%o9) -- + -- = 1
Rp Lp
So one of the equations has a product Xs*Xp and the other has the ratio Xs/Xp. Maybe that helps direct the search for additional data.
At this point I don't know what more can be said. If anyone can comment on this point I would be interested to hear it.
EDIT: OP says that the goal is to solve for Rp and Lp in terms of Rs and Ls. Given that, we can solve the two equations we obtained in %o7.
(%i10) %o7[2];
2
(%o10) Lp Ls w - Rp Rs = 0
(%i11) solve ([%o9, %o10], [Rp, Lp]);
2 2 2 2 2 2
Ls w + Rs Ls w + Rs
(%o11) [[Rp = ------------, Lp = ------------], [Rp = 0, Lp = 0]]
Rs 2
Ls w
(%i12) subst (%o11[1], [%o9, %o10]);
2 2 2
Ls w Rs
(%o12) [------------ + ------------ = 1, 0 = 0]
2 2 2 2 2 2
Ls w + Rs Ls w + Rs
(%i13) ratsimp(%);
(%o13) [1 = 1, 0 = 0]

Maxima CAS - substitution

I am trying to simplify a differential equation via substitution in maxima. However, the substitution does not seem to be working.
Here's my code:
depends (\rho,[t, r, \theta, z]); depends (V, [t, r, \theta, z]);
f_contin : diff (\rho, t) + diff (\rho*r*V[r], r)*(1/r) = 0;
base : diff (V[b]*r*\rho, r) = 0;
V_sub : V[r] = V[b] + \epsilon*V[r];
subst (V_sub, f_contin);
subst (base, %o6);
The last substitution did not work. What am I doing wrong here?
For clarity I add a Screenshot here:
The problem is that subst(a=b, c) (or equivalently subst(b, a, c)) can only make substitutions when a is an exact subexpression of c.
ratsubst (which see) can handle some cases when a is not an exact subexepression but in this case it doesn't seem to work.
But I think you can get the result you want by just subtracting the one equation from the other. Note that (a=b) - (c=d) yields a - c = b - d. Note also that I've put in another step (in %i7) to apply the diff operator. Also I've multiplied %o7 by r to get something like base.
(%i1) depends (\rho,[t, r, \theta, z]); depends (V, [t, r, \theta, z]);
(%o1) [rho(t, r, theta, z)]
(%o2) [V(t, r, theta, z)]
(%i3) f_contin : diff (\rho, t) + diff (\rho*r*V[r], r)*(1/r) = 0;
drho d
r V ---- + r (-- (V )) rho + V rho
drho r dr dr r r
(%o3) ---- + ------------------------------------ = 0
dt r
(%i4) base : diff (V[b]*r*\rho, r) = 0;
drho d
(%o4) V r ---- + (-- (V )) r rho + V rho = 0
b dr dr b b
(%i5) V_sub : V[r] = V[b] + \epsilon*V[r];
(%o5) V = epsilon V + V
r r b
(%i6) subst (V_sub, f_contin);
drho drho d
(%o6) ---- + (r (epsilon V + V ) ---- + r (-- (epsilon V + V )) rho
dt r b dr dr r b
+ (epsilon V + V ) rho)/r = 0
r b
(%i7) %o6, nouns;
drho drho d d
(%o7) ---- + (r (epsilon V + V ) ---- + r (epsilon (-- (V )) + -- (V )) rho
dt r b dr dr r dr b
+ (epsilon V + V ) rho)/r = 0
r b
(%i8) expand (r*%o7 - base);
drho drho d
(%o8) r ---- + epsilon r V ---- + epsilon r (-- (V )) rho + epsilon V rho = 0
dt r dr dr r r
The function subst (a,b,c) substitutes a for b in c. It uses 3 arguments, your first subst works because its interpreted as subst (V[b] + \epsilon*V[r],V[r], f_contin);
Your second subst is probably interpreted as subst (0,diff (V[b]*r*\rho, r),%) therefor nothing is substituted. What do you want to substitute for what?

Recursively computing an N x N matrix determinant

I'm having an issue with this implementation. It's giving me an error that "this expression to have type bool but here has unit" on the entire block starting at the first for loop and ending with the pown expression.
I'm not entirely sure what this means.
let rec detMat (m : int[,] ) : int =
let mutable det = 0
let mutable n = m.Length
let mutable i = 0
let mutable j = 0
let mutable j = 0
let mutable j1 = 0
let mutable j2 = 0
let mTmp = Array2D.create 0
if n = 1 then
det = m.[0, 0]
elif n = 2 then
det = m.[0, 0] * m.[1, 1] - m.[1, 0] * m.[0, 1]
else
det = 0
for j1 = 0 to n do
for i = 1 to n do
j2 = 0
for j = 0 to n do
if j <> j1 then
mTmp.[i-1, j2] <- m.[i, j]
j2 = j2 + 1
pown -1 (1 + j1 + 1) * m.[0, j1] * detMat(mTmp, n-1)
det
<- is the assignment operator for mutable variables.
Your code should be
det <- m.[0, 0]
det <- m.[0, 0] * m.[1, 1] - m.[1, 0] * m.[0, 1]
j2 <- j2 + 1
= is for equality, that's why you are getting the "this expression to have type bool" error. The second part, "but here has unit", means the compiler is expecting an arm of if to return a unit in the last expression. Carefully read this page to understand why the error message is so confusing: https://msdn.microsoft.com/en-us/library/dd233231.aspx

OCaml: Stream.peek without consuming line?

I'm working on a program that iterates over an input file, with a variable number of 'programs', and ending in '0'. My function run works fine if I start it from the top of the file, but for some reason a line is consumed by peeking to see if the next char is '0' (indicating the end of the file).
Here's my code:
let line_stream_of_channel channel =
Stream.from
(fun _ ->
try Some (input_line channel) with End_of_file -> None);;
let in_channel = open_in "dull.in" in
let line_stream = line_stream_of_channel in_channel in
while Stream.peek line_stream != Some "0" do
run in_channel;
print_string "...\n";
done;;
From what I've read, Stream.peek shouldn't consume a line, so maybe the problem doesn't come from that, but if not, I can't figure out what's doing it. Any ideas?
Edit Here's the entirety of my program:
let hello c =
print_char c;;
let hello_int c =
print_int c;
print_char '\n';;
let ios = int_of_string;;
let rec print_string_list = function
[] -> print_string "\n"
| h::t -> print_string h ; print_string " " ; print_string_list t;;
let rec print_int_list = function
[] -> print_string "\n"
| h::t -> print_int h ; print_string " " ; print_int_list t;;
let rec append l i =
match l with
[] -> [i]
| h :: t -> h :: (append t i);;
let line_stream_of_channel channel =
Stream.from
(fun _ ->
try Some (input_line channel) with End_of_file -> None);;
let string_to_int_list str_list int_list=
let len = List.length str_list in
for i = 0 to len - 1 do
int_list := append !int_list (ios (List.nth str_list i));
done;;
let get_option = function
| Some x -> x
| None -> raise (Invalid_argument "Option.get");;
let chomp_line ns in_channel =
let s = input_line in_channel in
let len = String.length s in
let start_pos = ref 0 in
for i = 0 to len do
if i == len then
let word = String.sub s !start_pos (i - !start_pos) in
ns := append !ns word;
else if s.[i] == ' ' then
let word = String.sub s !start_pos (i - !start_pos) in
ns := append !ns word;
start_pos := i + 1;
done;;
let run in_channel =
let ns = ref [] in
chomp_line ns in_channel;
let n = ios (List.nth !ns 0) in
let p = ios (List.nth !ns 1) in
let s = ios (List.nth !ns 2) in
print_string "num dulls: "; hello_int n;
print_string "num programs: "; hello_int p;
print_string "num state transitions: "; hello_int s;
let dull_sizes = ref [] in
chomp_line dull_sizes in_channel;
let int_dull_sizes = ref [] in
string_to_int_list !dull_sizes int_dull_sizes;
print_string "size of dulls: "; print_int_list !int_dull_sizes;
let program_sizes = ref [] in
let program_dulls = ref [] in
for i = 0 to p - 1 do
let program = ref [] in
chomp_line program in_channel;
program_sizes := append !program_sizes (List.nth !program 0);
program_dulls := append !program_dulls (List.nth !program 1);
done;
let int_program_sizes = ref [] in
string_to_int_list !program_sizes int_program_sizes;
print_string "program sizes: "; print_int_list !int_program_sizes;
print_string "program dulls: "; print_string_list !program_dulls;
let transitions = ref [] in
chomp_line transitions in_channel;
let int_transitions = ref [] in
string_to_int_list !transitions int_transitions;
for i = 0 to s - 1 do
hello_int (List.nth !int_transitions i)
done
;;
let in_channel = open_in "dull.in" in
let line_stream = line_stream_of_channel in_channel in
while Stream.peek line_stream <> Some "0" do
run in_channel;
done;;
And here's a sample input:
2 2 3
500 600
100 A
200 B
2 1 2
5 4 8
100 400 200 500 300
250 AC
360 ACE
120 AB
40 DE
2 3 4 -3 1 2 -2 1
0
(!=) is physical (pointer) inequality, and the test fails to detect your end mark 0. When 0 is peeked, Stream.peek returns Some 0, but it is a different entity from Some 0 of the right hand of the inequality check, and therefore the loop never terminates until it crashes at EOF.
The following demonstrates what is happening:
# Some 0 != Some 0;;
- : bool = true
# let x = Some 0 in x != x;;
- : bool = false
Use (<>), structural inequality here. Except it and the omitted run_in_channel part, the code works fine for me.
A golden rule: do not use physical equality (==) and (!=) unless you really need them. Normally, stick to structural equalities (=) and (<>).
-- edit --
There was another issue in the code which was not originally revealed.
Once you create a stream from an in_channel. Do not touch it by yourself, until you want to close it by close_in! Let the stream the only reader of it.
The benefit of the stream is that once created, you are freed from taking care of when the actual readings happen. You could still access the channel directly, but it just ruins the benefit completely. Just do not do it. Use Stream.next or Stream.peek instead of input_line in your run.

F# fails with "Error 4 This expression was expected to have type int but here has type int -> int"

Here is the code that I am trying to get to work last line is where it is failing:
let rec gcd a b =
if b= 0 then
a
else
gcd b (a % b);;
let n = 8051
let mutable d = 0
let mutable c = 1
let mutable xi = 2
let mutable yi = 2
let f x = (pown x 2) + (c % n);;
while c < 100 do
while d = 1 do
xi <- (f xi)
yi <- (f(f(yi)))
printfn "%d%d" xi yi
d <- gcd(abs (xi - yi) n)
---------------------The Following Code works; Except for integer overflow on N---------
module Factorization
let rec gcd a b =
if b= 0 then
a
else
gcd b (a % b);;
let n = 600851475143N
let mutable d, c, xi, yi = 1, 1, 2, 2
let f x = (pown x 2) + (c % n);;
let maxN m =int(ceil(sqrt(float m)))
//if (n > maxN(xi)) && (n > maxN(yi)) then
while c < 100 do
d <- 1
while d = 1 do
if (maxN(n) > xi) && (maxN(n) > yi) then
xi <- f xi
yi <- f(f(yi))
d <- gcd (abs (xi - yi)) n
//fail
if d = n then d<-1
if d <> 1 then printfn "A prime factor of %d x = %d, y = %d, d = %d" n xi yi d
else
xi <- 2
yi <- 2
c <- c + 1;;
In addition to what #Rangoric pointed out, the outer brackets have to go as well otherwise currying won't work:
d <- gcd (abs(xi-yi)) n
Yikes, here are a few unsolicited tips (#BrokenGlass answered the question itself correctly).
First, you can assign all those mutables in one line:
let mutable d, c, xi, yi = 0, 1, 2, 2
Second, go easy on the parentheses:
xi <- f xi
yi <- f (f yi)
And of course, try to get rid of the mutables and while loops. But I'll leave that to you since I'm sure you are aware seeing that you implemented gcd using recursion.
Try:
d <- gcd (abs(xi-yi)) n
It is pointing out that abs is a int->int and not an int by itself. Wrapping it in parentheses causes the abs to be executed before gcd looks at it. This causes gcd to see the result of abs instead of abs itself.

Resources