4

It seems that I can't assign an abstract value to a ref and I'm not sure what to do.

open Big_int
let largest = ref zero_big_int;;
let depth = ref zero_big_int;;
let rec big i = (add_int_big_int i zero_big_int)
and collatz = fun num depth ->
  print_endline (string_of_big_int num);
  (if(eq_big_int  (add_int_big_int (-1) num) zero_big_int)then(depth)else(
    if eq_big_int (mod_big_int num (big 2)) zero_big_int then (collatz (div_big_int num (big 2)) (succ_big_int depth)) else (collatz (succ_big_int (mult_int_big_int 3 num)) (succ_big_int depth))))
and euler14 i =
  print_endline (string_of_big_int i);
  (if(lt_big_int i (big 1000000))then (
    let ret = (collatz i unit_big_int) in
    if(ret> !depth)then (largest:=i;depth:=ret; (euler14 (succ_big_int i))) else (euler14 (succ_big_int i))
  ) else (!largest));;
print_endline (string_of_big_int (euler14 (big 2)));;

The code seems to crash when I try largest:=i and depth:=ret which are both Big_nums. Is there any way around this?

2
2
1
3
3
10
5
16
8
4
2
1
Fatal error: exception Invalid_argument("equal: abstract value")
drellem
  • 43
  • 3

2 Answers2

6

You cannot compare values of type Big_int.big_int with the polymorphic =, >, >=. Instead, you have to write your own comparison functions for all types that contain a Big_int.big_int, even if it is deeply embedded.

Using OCaml 3.12.1 or later, you can use the polymorphic comparison functions with values of type Z.t as implemented in the external library Zarith, a modern replacement for Big_int.

Being compatible with polymorphic operations is only one of the advantages of Zarith over Big_int. It is also more compact in memory, and faster.

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
0

The thing that's failing seems to be the polymorphic comparison ret > !depth, not the assignment to a ref. I would assume you can use Big_int.compare_big_int.

# let x = big_int_of_int 3;;
val x : Big_int.big_int = <abstr>
# let y = big_int_of_int 4;;
val y : Big_int.big_int = <abstr>
# x > y;;
Exception: Invalid_argument "equal: abstract value".
# compare_big_int x y;;
- : int = -1
# 

(Polymorphic comparison is one of the touchy spots in OCaml.)

Jeffrey Scofield
  • 65,646
  • 2
  • 72
  • 108