Why this parametric constructor only works with multiline definition? - julia

I have a Device constructor that only works if I define it using the multiline function syntax, but it fails if I define it with the one line function syntax, with the following error:
ERROR: LoadError: UndefVarError: F not defined (if I remove F) or
ERROR: LoadError: UndefVarError: C not defined
However it also works if I only remove the F and C type parameters from the method signature (but not the where {C<:UxnCpu, F<:Function} part).
69 abstract type AbstractCPU end
70 mutable struct Device{C<:AbstractCPU, F<:Function}
71 cpu::C
72 id_addr::Int
73 vector::UInt16
74 talk::F
75 mem::OVector{UInt8}
76 dat::OVector{UInt8}
77 end
78
79 function Device(cpu::C, id_addr::Int, talkfn::F)::Device where {C<:AbstractCPU, F<:Function}
80 d = Device(cpu, id_addr, 0x000, talkfn, cpu.ram.dat, OVector{UInt8}(0x10))
81 cpu.dev[id_addr] = d
82
83 return d
84 end
85
---> 86 Device(talkfn::F, cpu::C, id_addr::Int)::Device where {C<:AbstractCPU, F<:Function} = Device(cpu, id_addr, talkfn)
87
88 Device(cpu, id_addr::Int) where {C<:AbstractCPU} = begin
89 Device(cpu, id_addr) do d::Device, b0::UInt8, w::UInt8
90 return true
91 end
92 end
The full stack trace is:
ERROR: LoadError: UndefVarError: F not defined
Stacktrace:
[1] top-level scope
# C:\Users\ismae\Bin\uxn-dev\src\VarvaraEmulator.jl:86 <---
[2] include(fname::String)
# Base.MainInclude .\client.jl:444
[3] top-level scope
# REPL[6]:1
in expression starting at C:\Users\ismae\Bin\uxn-dev\src\VarvaraEmulator.jl:25
However this workarounds do work:
Device(talkfn, cpu, id_addr::Int)::Device where {C<:AbstractCPU, F<:Function} = Device(cpu, id_addr, talkfn)
I would have thought it would complain with something about to few type parameters in signature.
The following syntax doesn't work either:
Device(talkfn::F, cpu::C, id_addr::Int)::Device where {C<:AbstractCPU, F<:Function} = begin
Device(cpu, id_addr, talkfn)
end
However this does, which is what I left in the end:
function Device(talkfn::F, cpu::C, id_addr::Int)::Device where {C<:AbstractCPU, F<:Function}
Device(cpu, id_addr, talkfn)
end
I would like to understand where that error is coming from, what am I doing wrong?
I tried to replicate it in a minimal example, but I was not able to, here is my the complete code for reference:
https://github.com/Ismael-VC/VarvaraEmulator.jl/blob/VarvaraEmulator.jl/src/VarvaraEmulator.jl#L69-L99
This is my current setup:
julia> versioninfo()
Julia Version 1.6.3
Commit ae8452a9e0 (2021-09-23 17:34 UTC)
Platform Info:
OS: Windows (x86_64-w64-mingw32)
CPU: Intel(R) Core(TM) i7-4710HQ CPU # 2.50GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-11.0.1 (ORCJIT, haswell)
Environment:
JULIA_LOAD_PATH = C:\Users\\smae\Bin\uxn-dev\src;
(#v1.6) pkg> status
Status `C:\Users\ismae\.julia\environments\v1.6\Project.toml`
[6e4b80f9] BenchmarkTools v1.2.0
[c43c736e] Genie v3.2.0
[7eb4fadd] Match v1.1.0
[6fe1bfb0] OffsetArrays v1.10.7
[c3e4b0f8] Pluto v0.16.1
[b873ce64] ReplMaker v0.2.5
[98e33af6] SimpleDirectMediaLayer v0.3.0
[90137ffa] StaticArrays v1.2.13
Best regards.

I think it's just an issue parsing the parameters when there is a return type annotation, not your fault. I can replicate the error with a much more minimal example.
These work:
function f1(x::F, y::C) where {F<:Integer, C<:Complex}
1
end
function f2(x::F, y::C)::Int where {F<:Integer, C<:Complex}
2
end
g1(x::F, y::C) where {F<:Integer, C<:Complex} = 3
But this doesn't:
g2(x::F, y::C)::Int where {F<:Integer, C<:Complex} = 4
Edit: From the comments, the last case can be fixed by adding parentheses:
(g2(x::F, y::C)::Int) where {F<:Integer, C<:Complex} = 4

Related

Using Rcpp, how to convert RawVector back/forth to a string?

There is a discussion on Rccp-dev discussing how to convert from a string result to a RawVector (see https://lists.r-forge.r-project.org/pipermail/rcpp-devel/2010-October/001179.html).
// [[Rcpp::export]]
RawVector say_hello()
{
std::string res = "hello friend";
RawVector raw( res.size() ) ;
std::copy( res.begin(), res.end(), raw.begin() ) ;
return raw ;
}
It works as expected:
> Rcpp::sourceCpp( paste0(wd, "src/base64.cpp") );
> say_hello()
[1] 68 65 6c 6c 6f 20 66 72 69 65 6e 64
> charToRaw("hello friend")
[1] 68 65 6c 6c 6f 20 66 72 69 65 6e 64
Question: How to go the other direction in Rcpp?
If I have a RawVector how to transform it to a std::string? That is the equivalent of the rawToChar function within Rcpp?
> rawToChar ( charToRaw("hello friend") )
[1] "hello friend"
Clarification
Analogous to the above code with rawToChar and charToRaw, I want to have the following: print_hello(say_hello()) which should output "hello friend".
That is, I am trying to pass in a raw vector from R and have it convert the raw format to a std:string:
ONE FAILED attempt
// [[Rcpp::export]]
std::string print_hello(const RawVector& raw)
{
// https://stackoverflow.com/questions/8421250/convert-rcppcharactervector-to-stdstring
std::string res = Rcpp::as<std::string>(raw);
return res ;
}
ANOTHER FAILED ATTEMPT (THIS IS THE FORMAT I AM LOOKING FOR)
Here I included the Rccp serialize API: #include "RApiSerializeAPI.h"
#include "RApiSerializeAPI.h
std::string print_hello(const RawVector raw)
{
// https://github.com/eddelbuettel/rcppredis/blob/master/src/Redis.cpp
std::string res = unserializeFromRaw(raw);
return res ;
}
The errors are always similar:
base64.cpp:155:38: error: conversion from 'SEXP' {aka 'SEXPREC*'} to non-scalar type 'std::string' {aka 'std::__cxx11::basic_string<char>'} requested
155 | std::string res = unserializeFromRaw(raw);
A final try, also fails
std::string print_hello(SEXP s)
{
// https://github.com/eddelbuettel/rcppredis/blob/master/src/Redis.cpp
Rcpp::RawVector raw = (TYPEOF(s) == RAWSXP) ? s : serializeToRaw(s);
std::string res = unserializeFromRaw(raw);
return res ;
}
There is a reference to a static_cast that I don't understand as well. The goal is: convert a RawVector to a std::string
I am swimming in deep waters here, just looking for a bit of guidance.
Windoze info
/*
g++ -std=gnu++11 -I"C:/PROGRA~1/R/R-42~1.1/include" -DNDEBUG -I"C:/Users/......./AppData/Local/R/WIN-LI~1/4.2/Rcpp/include" -I"C:/_git_/github/......./src" -I"C:/_git_/github/......./inst/include" -I"C:/rtools42/x86_64-w64-mingw32.static.posix/include" -O2 -Wall -mfpmath=sse -msse2 -mstackrealign -c base64.cpp -o base64.o
R_RTOOLS42_PATH
C:\rtools42/x86_64-w64-mingw32.static.posix/bin;C:\rtools42/usr/bin
"pkg.version(Rcpp)"
[1] ‘1.0.9’
> R.version
_
platform x86_64-w64-mingw32
arch x86_64
os mingw32
crt ucrt
system x86_64, mingw32
status
major 4
minor 2.1
year 2022
month 06
day 23
svn rev 82513
language R
version.string R version 4.2.1 (2022-06-23 ucrt)
nickname Funny-Looking Kid
*/
Dirk's answer
> r = (charToRaw("The quick brown fox"))
> r
[1] 54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f 78
> r2c(r)
[1] "The quick brown fox"
> r2c(charToRaw("The quick brown fox"))
[1] "The quick brown fox\xd2\xce\002"
### BAFFLING ### Windoze!?<!?
> r <- charToRaw("The quick brown fox")
> r2c(r)
[1] "The quick brown fox\xdb\xce\002"
> r = (charToRaw("The quick brown fox"))
> r2c(r)
[1] "The quick brown fox"
As hinted in the comments, the answer is hidden away in the RcppRedis package from which I just borrowed this actual one-liner (which I broke up onto three lines for nice display here):
> Rcpp::cppFunction("std::string r2c(RawVector x) { \
const char *c = reinterpret_cast<char*>(x.begin()); \
return std::string(c); }")
> r <- charToRaw("The quick brown fox")
> r
[1] 54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f 78
> r2c(r)
[1] "The quick brown fox"
>
We basically just ask C++ to 'view' the raw chars as standard chars. There is likely also a C function in R itself you could borrow. This worked for me, and apparently since at least 2014.

Julia 1.7.2 : how to use #sprintf

I am new to julia 1.7.2. I found on julialang.org about #sprintf.
I try to show a number 45 as: 00045
a = #sprintf "%05i" 45 # I get: #sprintf not defined
a = Printf.#sprintf "%05i" 45 # I get: Printf not defined
What is missing in this 1 line program? Thanks
You need to import the Printf module first. For example with using (in which case you do not need to prefix #sprintf with Printf):
julia> using Printf
julia> #sprintf "%05i" 45
"00045"

Chainer: AttributeError: module 'chainer.distributions' has no attribute 'Independent'

Problem on using API named Independent.
I am using --
Chainer: 5.4.0
NumPy: 1.15.4
CuPy:
CuPy Version : 5.4.0
CUDA Root : /usr/local/cuda-10.0
CUDA Build Version : 10000
CUDA Driver Version : 10010
CUDA Runtime Version : 10000
cuDNN Build Version : 7401
cuDNN Version : 7401
NCCL Build Version : 2307
NCCL Runtime Version : 2307
iDeep: 2.0.0.post3
Does in version 5.4.0 in Chainer.distribution- Class Independent is removed ?
I tried to use the distribution class directly although requirement of Independent class was required.
I am using the below link model.
VAE Network
I am not using Binary dataset and changed according to my own custom dataset.
chainer/network.py in forward(self, x)
22
23 def forward(self, x):
---> 24 q_z = self.encoder(x)
25 z = q_z.sample(self.k)
26 p_x = self.decoder(z)
~/anaconda3/envs/chainer_p36/lib/python3.6/site-packages/chainer/link.py in __call__(self, *args, **kwargs)
240 if forward is None:
241 forward = self.forward
--> 242 out = forward(*args, **kwargs)
243
244 # Call forward_postprocess hook
chainer/network.py in forward(self, x)
50 mu = self.mu(h)
51 ln_sigma = self.ln_sigma(h) # log(sigma)
---> 52 return D.Independent(D.Normal(loc=mu, log_scale=ln_sigma))
53
54
AttributeError: module 'chainer.distributions' has no attribute 'Independent'
D.Independent is a new feature introduced in Chainer v6.0.0. You need to update Chainer.

Change julia promt to include evalutation numbers

When debugging or running julia code in REPL, I usually see error messages showing ... at ./REPL[161]:12 [inlined].... The number 161 means the 161-th evaluation in REPL, I guess. So my question is could we show this number in julia's prompt, i.e. julia [161]> instead of julia>?
One of the advantages of Julia is its ultra flexibility. This is very easy in Julia 0.7 (nightly version).
julia> repl = Base.active_repl.interface.modes[1]
"Prompt(\"julia> \",...)"
julia> repl.prompt = () -> "julia[$(length(repl.hist.history) - repl.hist.start_idx + 1)] >"
#1 (generic function with 1 method)
julia[3] >
julia[3] >2
2
julia[4] >f = () -> error("e")
#3 (generic function with 1 method)
julia[5] >f()
ERROR: e
Stacktrace:
[1] error at .\error.jl:33 [inlined]
[2] (::getfield(, Symbol("##3#4")))() at .\REPL[4]:1
[3] top-level scope
You just need to put the first 2 lines onto your ~/.juliarc and enjoy~
Since there are several changes in the REPL after julia 0.7, these codes do not work in old versions.
EDIT: Well, actually there need a little bit more efforts to make it work in .juliarc.jl. Try this code:
atreplinit() do repl
repl.interface = Base.REPL.setup_interface(repl)
repl = Base.active_repl.interface.modes[1]
repl.prompt = () -> "julia[$(length(repl.hist.history) - repl.hist.start_idx + 1)] >"
end

Speeding up AVR function pointers

I have a program for avr where I would like to use a pointer to a method. But why is using function pointer over normal call almost 4 times slower?? And how do I speed it up?
I have:
void simple_call(){ PORTB |= _BV(1); }
void (*simple)() = &simple_call;
Then if I compile with -O3 and call:
simple_call()
it takes 250ns to complete. If I instead call:
simple()
it takes 960ns to complete!!
How can I make it faster?
why is it slower??
You see a 710 ns increase in time. For a 16 MHz clock, that time is 11 ticks.
It is not really fair to say 4X because the time increase is a constant overhead for the function pointer. In your case, the function body is tiny, so the overhead is relatively large. But if you had a case where the function was large and took 1 ms to execute, the time increase would still be 710 ns and you would be asking why does the function pointer take 0.07% longer?
To see why one approach is faster than another, you need to get at the assembler code. Using build tools such as Eclipse allows you the get an assembler listing from the GCC compiler by adding command line options not available with the Arduino IDE. This is invaluable to figure out what is going on.
Here is a section of the assembler listing showing what you think is going on:
simple_call();
308: 0e 94 32 01 call 0x264 ; 0x264 <_Z11simple_callv>
simple();
30c: e0 91 0a 02 lds r30, 0x020A
310: f0 91 0b 02 lds r31, 0x020B
314: 19 95 eicall
These listings show the source code and assembler produced by the compiler. To make sense of that and figure out timing, you need the Atmel AVR instruction reference which contains descriptions of every instruction and the number of clock ticks they take. The simple_call() is maybe what you expect and takes 4 ticks. The simple() says:
LDS = load address byte - 2 ticks
LDS = load address byte - 2 ticks
EICALL = indirect call to address loaded - 4 ticks
Those both call the function simple_call():
void simple_call(){ PORTB |= _BV(1); }
264: df 93 push r29
266: cf 93 push r28
268: cd b7 in r28, 0x3d ; 61
26a: de b7 in r29, 0x3e ; 62
26c: a5 e2 ldi r26, 0x25 ; 37
26e: b0 e0 ldi r27, 0x00 ; 0
270: e5 e2 ldi r30, 0x25 ; 37
272: f0 e0 ldi r31, 0x00 ; 0
274: 80 81 ld r24, Z
276: 82 60 ori r24, 0x02 ; 2
278: 8c 93 st X, r24
27a: cf 91 pop r28
27c: df 91 pop r29
27e: 08 95 ret
So the function pointer should take just 4 more ticks and be small compared to all the instructions in the function method.
Above, I said should and what you think is going on. I lied a bit: the assembler above is for no optimizations.
You used the optimization -O3 which changes everything.
With the optimizations, the function body gets squashed to almost nothing:
void simple_call(){ PORTB |= _BV(1); }
264: 29 9a sbi 0x05, 1 ; 5
266: 08 95 ret
That is 2 + 4 ticks. The compiler gurus have coded the compiler to figure out a much better way to execute the one line of C++. But wait there is more. When you "call" your function the compiler says "why do that? it is just one assembler instruction". The compiler decides your call is pointless and puts the instructions inline:
void simple_call(){ PORTB |= _BV(1); }
2d6: 29 9a sbi 0x05, 1 ; 5
But with the optimizations, the function pointer call remains a call:
simple();
2d8: e0 91 0a 02 lds r30, 0x020A
2dc: f0 91 0b 02 lds r31, 0x020B
2e0: 19 95 eicall
So lets see if the math adds up. With the inline, the "call" is 3 ticks. The indirect call is 8 + 6 = 14. The difference is 11 ticks! (I can add!)
So that is **why*.
how do I speed it up?
You don't need to: It is only 4 clock ticks more to make a function pointer call. Except for the most trivial functions, it does not matter.
You can't: Even if you try to inline the functions, you still need a conditional branch. A bunch of load, compare, and conditional jumps will take more than the indirect call. In other words, the function pointer is a better method of branching than any conditional.

Resources