|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| module boolean_spectral_lens
|
| use, intrinsic :: iso_c_binding, only: c_int64_t, c_ptr, c_f_pointer, &
|
| c_size_t, c_loc, c_null_ptr, c_associated, c_char, c_null_char
|
| use, intrinsic :: iso_fortran_env, only: int64, real64, int8, error_unit
|
| use sov_monster_kernel, only: dp, ci, czero, &
|
| sov_blake3_hash_matrix, sov_bifrost_sign, &
|
| sov_is_hermitian_matrix, sov_is_density_matrix, sov_fault, &
|
| blake3_state, sov_blake3_init, sov_blake3_update, sov_blake3_finalize, &
|
| i8
|
| use spe_encoder, only: spe_frame_t, spe_encode, spe_decode, spe_verify_frame
|
| implicit none
|
| private
|
|
|
|
|
|
|
|
|
| public :: boolean_to_spectral
|
| public :: spectral_to_boolean
|
| public :: watch_sum_one
|
| public :: lisp_world_dump_step
|
| public :: spectral_and
|
| public :: spectral_or
|
| public :: spectral_not
|
| public :: spectral_xor
|
| public :: inverted_lens_t
|
|
|
|
|
|
|
|
|
| type, bind(C) :: inverted_lens_t
|
| integer(c_int64_t) :: rank
|
| type(c_ptr) :: frame_ptr
|
| type(c_ptr) :: density_ptr
|
| type(c_ptr) :: eigenvalues_ptr
|
| type(c_ptr) :: lisp_output_ptr
|
| integer(c_int64_t) :: lisp_buffer_size
|
| integer(c_int64_t) :: step
|
| end type
|
|
|
| contains
|
|
|
|
|
|
|
|
|
|
|
| subroutine boolean_to_spectral(bool_ptr, bool_len, frame, eigenvalues_ptr, density_ptr, plasma_ok) &
|
| bind(C, name="boolean_to_spectral")
|
| type(c_ptr), intent(in), value :: bool_ptr
|
| integer(c_size_t), intent(in), value :: bool_len
|
| type(spe_frame_t), intent(in) :: frame
|
| type(c_ptr), intent(in), value :: eigenvalues_ptr, density_ptr
|
| integer(c_int64_t), intent(out) :: plasma_ok
|
| integer(c_int64_t) :: r, d, i, j, k
|
| integer(c_int64_t), pointer :: bool_vec(:)
|
| real(dp), pointer :: eigenvalues(:)
|
| complex(dp), pointer :: density(:,:), frame_arr(:,:,:)
|
| real(dp) :: s
|
| complex(dp) :: acc
|
|
|
|
|
| r = frame%rank; d = frame%dim
|
| call c_f_pointer(bool_ptr, bool_vec, [int(bool_len)])
|
| call c_f_pointer(eigenvalues_ptr,eigenvalues, [r])
|
| call c_f_pointer(density_ptr, density, [d, d])
|
| call c_f_pointer(frame%frame_ptr,frame_arr, [r, d, d])
|
|
|
|
|
| do i = 1, r
|
| if (i <= int(bool_len) .and. bool_vec(i) /= 0) then
|
| eigenvalues(i) = 1.0_dp
|
| else
|
| eigenvalues(i) = 10.0_dp * epsilon(0.0_dp)
|
| end if
|
| end do
|
| s = sum(eigenvalues); eigenvalues = eigenvalues / s
|
|
|
|
|
| density = czero
|
|
|
| do j = 1, d
|
| do k = 1, d
|
| acc = czero
|
| do i = 1, r; acc = acc + eigenvalues(i)*frame_arr(i,j,k); end do
|
| density(j,k) = acc
|
| end do
|
| end do
|
|
|
|
|
| plasma_ok = 0
|
| if (sov_is_density_matrix(density, d)) plasma_ok = 1
|
| if (plasma_ok == 0) call sov_fault(501)
|
| end subroutine
|
|
|
|
|
|
|
|
|
| subroutine spectral_to_boolean(eigenvalues_ptr, rank, threshold, bool_out_ptr) &
|
| bind(C, name="spectral_to_boolean")
|
| type(c_ptr), intent(in), value :: eigenvalues_ptr, bool_out_ptr
|
| integer(c_int64_t), intent(in), value :: rank
|
| real(dp), intent(in), value :: threshold
|
| real(dp), pointer :: eigenvalues(:)
|
| integer(c_int64_t), pointer :: bool_out(:)
|
| integer(c_int64_t) :: i
|
|
|
|
|
| call c_f_pointer(eigenvalues_ptr, eigenvalues, [rank])
|
| call c_f_pointer(bool_out_ptr, bool_out, [rank])
|
| do i = 1, rank
|
| if (eigenvalues(i) > threshold) then
|
| bool_out(i) = 1
|
| else
|
| bool_out(i) = 0
|
| end if
|
| end do
|
| end subroutine
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| subroutine spectral_and(a_ptr, b_ptr, r, out_ptr) &
|
| bind(C, name="spectral_and")
|
| type(c_ptr), intent(in), value :: a_ptr, b_ptr, out_ptr
|
| integer(c_int64_t), intent(in), value :: r
|
| real(dp), pointer :: a(:), b(:), out(:)
|
| call c_f_pointer(a_ptr, a, [r])
|
| call c_f_pointer(b_ptr, b, [r])
|
| call c_f_pointer(out_ptr, out, [r])
|
| out = a * b
|
| out = out / max(sum(out), epsilon(0.0_dp))
|
| end subroutine
|
|
|
|
|
| subroutine spectral_or(a_ptr, b_ptr, r, out_ptr) &
|
| bind(C, name="spectral_or")
|
| type(c_ptr), intent(in), value :: a_ptr, b_ptr, out_ptr
|
| integer(c_int64_t), intent(in), value :: r
|
| real(dp), pointer :: a(:), b(:), out(:)
|
| call c_f_pointer(a_ptr, a, [r])
|
| call c_f_pointer(b_ptr, b, [r])
|
| call c_f_pointer(out_ptr, out, [r])
|
| out = a + b - a*b
|
| out = max(out, 0.0_dp)
|
| out = out / max(sum(out), epsilon(0.0_dp))
|
| end subroutine
|
|
|
|
|
| subroutine spectral_not(a_ptr, r, out_ptr) &
|
| bind(C, name="spectral_not")
|
| type(c_ptr), intent(in), value :: a_ptr, out_ptr
|
| integer(c_int64_t), intent(in), value :: r
|
| real(dp), pointer :: a(:), out(:)
|
| call c_f_pointer(a_ptr, a, [r])
|
| call c_f_pointer(out_ptr, out, [r])
|
| out = 1.0_dp/real(r,dp) - a + 1.0_dp/real(r,dp)
|
| out = max(out, 10.0_dp*epsilon(0.0_dp))
|
| out = out / sum(out)
|
| end subroutine
|
|
|
|
|
| subroutine spectral_xor(a_ptr, b_ptr, r, out_ptr) &
|
| bind(C, name="spectral_xor")
|
| type(c_ptr), intent(in), value :: a_ptr, b_ptr, out_ptr
|
| integer(c_int64_t), intent(in), value :: r
|
| real(dp), pointer :: a(:), b(:), out(:)
|
| call c_f_pointer(a_ptr, a, [r])
|
| call c_f_pointer(b_ptr, b, [r])
|
| call c_f_pointer(out_ptr, out, [r])
|
| out = a + b - 2.0_dp*a*b
|
| out = max(out, 10.0_dp*epsilon(0.0_dp))
|
| out = out / sum(out)
|
| end subroutine
|
|
|
|
|
|
|
|
|
|
|
|
|
| subroutine watch_sum_one(lens, max_steps, sk_ptr, plasma_ok) &
|
| bind(C, name="watch_sum_one")
|
| type(inverted_lens_t), intent(inout) :: lens
|
| integer(c_int64_t), intent(in), value :: max_steps
|
| type(c_ptr), intent(in), value :: sk_ptr
|
| integer(c_int64_t), intent(out) :: plasma_ok
|
| integer(c_int64_t) :: r, d, step, i
|
| real(dp), pointer :: eigenvalues(:)
|
| complex(dp), pointer :: density(:,:)
|
| type(spe_frame_t), pointer :: frame
|
| real(dp) :: trace_sum, trace_err
|
|
|
|
|
| r = lens%rank
|
| d = r
|
| call c_f_pointer(lens%eigenvalues_ptr, eigenvalues, [r])
|
| call c_f_pointer(lens%density_ptr, density, [d, d])
|
| call c_f_pointer(lens%frame_ptr, frame)
|
|
|
| plasma_ok = 1
|
|
|
| do step = 1, max_steps
|
| lens%step = step
|
|
|
|
|
| trace_sum = sum(eigenvalues)
|
| trace_err = abs(trace_sum - 1.0_dp)
|
| if (trace_err > 100.0_dp * epsilon(0.0_dp) * r) then
|
| plasma_ok = 0
|
| call sov_fault(601)
|
| end if
|
|
|
|
|
| if (.not. sov_is_density_matrix(density, d)) then
|
| plasma_ok = 0
|
| call sov_fault(602)
|
| end if
|
|
|
|
|
| call lisp_world_dump_step(lens, step, eigenvalues, density, trace_sum)
|
| end do
|
| end subroutine
|
|
|
|
|
|
|
|
|
|
|
|
|
| subroutine lisp_world_dump_step(lens, step, eigenvalues, density, trace_sum) &
|
| bind(C, name="lisp_world_dump_step")
|
| type(inverted_lens_t), intent(in) :: lens
|
| integer(c_int64_t), intent(in), value :: step
|
| real(dp), intent(in) :: eigenvalues(lens%rank)
|
| complex(dp), intent(in) :: density(lens%rank, lens%rank)
|
| real(dp), intent(in), value :: trace_sum
|
| character(len=:), allocatable :: sexpr
|
| character(len=32) :: step_str, trace_str, eig_str
|
| integer(c_int64_t) :: i, r
|
| character(c_char), pointer :: buf(:)
|
| integer :: slen
|
|
|
|
|
| r = lens%rank
|
| if (.not. c_associated(lens%lisp_output_ptr)) return
|
|
|
|
|
| write(step_str, '(I0)') step
|
| write(trace_str, '(F12.9)') trace_sum
|
|
|
| sexpr = '(world-state :step ' // trim(step_str) // &
|
| ' :trace ' // trim(trace_str) // &
|
| ' :trace-ok ' // merge('#t', '#f', abs(trace_sum-1.0_dp) < 1e-10_dp) // &
|
| ' :eigenvalues ('
|
|
|
| do i = 1, r
|
| write(eig_str, '(F12.9)') eigenvalues(i)
|
| sexpr = sexpr // trim(eig_str)
|
| if (i < r) sexpr = sexpr // ' '
|
| end do
|
| sexpr = sexpr // '))'
|
|
|
|
|
| slen = min(len(sexpr), int(lens%lisp_buffer_size) - 1)
|
| call c_f_pointer(lens%lisp_output_ptr, buf, [lens%lisp_buffer_size])
|
| do i = 1, slen
|
| buf(i) = sexpr(i:i)
|
| end do
|
| buf(slen+1) = c_null_char
|
| end subroutine
|
|
|
| end module boolean_spectral_lens
|
|
|