The following go code doesn't compile, because (I believe) there is a mistake around the way pointers are being referenced.
In particular, The error message is
prog.go:13: cannot use append((*x)[:remove], (*x)[remove + 1:]...) (type []int) as type *[]int in assignment
Here is an abstracted and simplified version of the code which results in this error message.
package main
import "fmt"
func main() {
x := &[]int{11, 22, 33, 44, 55, 66, 77, 88, 99}
for i, addr := range *x {
if addr == 22 {
for len(*x) > 5 {
remove := (i + 1) % len(*x)
x = append((*x)[:remove], (*x)[remove+1:]...)
}
break
}
}
fmt.Println(x)
}
You're not using an array here, you're using a slice. Generally, you don't want to handle a pointer to a slice since it can get awkward, and the pointer is needed in very few cases.
To fix your error, dereference x:
*x = append((*x)[:remove], (*x)[remove+1:]...)
But you should probably be using the slice value directly, so that no dereferences are required:
x := []int{11, 22, 33, 44, 55, 66, 77, 88, 99}
Related
I'd like to prove the correctness of this function from libsecp256k1:
static int secp256k1_ctz64_var_debruijn(uint64_t x) {
static const uint8_t debruijn[64] = {
0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
};
return debruijn[((x & -x) * 0x022FDD63CC95386D) >> 58];
}
My specification is
Definition secp256k1_ctz64_var_debruijn_spec : ident * funspec :=
DECLARE _secp256k1_ctz64_var_debruijn
WITH a : Z
PRE [ tulong ]
PROP(0 <= a < Int64.modulus)
PARAMS(Vlong (Int64.repr a))
SEP()
POST [ tint ]
PROP()
RETURN(Vint (Int.repr (Z.of_nat (ctz a))))
SEP().
for my own custom implementation of ctz : Z -> nat.
However when I go to prove the associated correctness lemma:
Lemma body_secp256k1_umul128: semax_body Vprog Gprog f_secp256k1_ctz64_var_debruijn secp256k1_ctz64_var_debruijn_spec.
Proof.
start_function.
forward.
I get an error:
Tactic failure: Cannot evaluate right-hand-side expression (sometimes this is caused by missing LOCALs in your precondition) (level 995).
My goal context is
1 goal
Espec : OracleKind
a : Z
Delta_specs : Maps.PTree.t funspec
Delta := abbreviate : tycontext
H : and (Z.le 0 a) (Z.lt a Int64.modulus)
POSTCONDITION := abbreviate : ret_assert
MORE_COMMANDS := abbreviate : statement
______________________________________(1/1)
semax Delta
(PROPx nil
(LOCALx (cons (temp _x (Vlong (Int64.repr a))) nil) (SEPx nil)))
(Ssequence
(Sset _t'1
(Ederef
(Ebinop Oadd (Evar _debruijn (tarray tuchar 64))
(Ebinop Oshr
(Ebinop Omul
(Ebinop Oand (Etempvar _x tulong)
(Eunop Oneg (Etempvar _x tulong) tulong) tulong)
(Econst_long (Int64.repr 157587932685088877) tlong)
tulong) (Econst_int (Int.repr 58) tint) tulong)
(tptr tuchar)) tuchar)) MORE_COMMANDS) POSTCONDITION
Notably the debruijn array and its content are absent from the context. Am I supposed to be adding v_debruijn to my specification in some manner when a function has a local static variable like this?
Though it's defined locally, debruijn is treated as a global variable in the clightgen generated Coq file.
So it seems like modifying your specification in the following way should at least get you started:
Definition secp256k1_ctz64_var_debruijn_spec : ident * funspec :=
DECLARE _secp256k1_ctz64_var_debruijn
WITH a : Z, gv : globals
PRE [ tulong ]
PROP(0 <= a < Int64.modulus)
PARAMS(Vlong (Int64.repr a))
GLOBALS(gv)
SEP(data_at Ers (tarray tuchar 64) (map (fun x => Vint (Int.repr x)) debruijn) (gv _debruijn))
POST [ tint ]
PROP()
RETURN(Vint (Int.repr (Z.of_nat (ctz a))))
SEP(data_at Ers (tarray tuchar 64) (map (fun x => Vint (Int.repr x)) debruijn) (gv _debruijn)).
where debruijn in the above definition is the appropriate list Z associated with your array.
Supplementary to TJ Machado's answer, the data for the debruijn array is stored in gvar_init v_debruijn in a somewhat unusual data structure specialized for static initialization. I haven't found a good canonical way to turn this into a suitable data_at expression, but I did manage to hack something together for my purposes:
Definition debruijn64_array (sh: share) (gv: globals) : mpred :=
Eval cbn in
let
is_all_init_int8 := fix is_all_init_int8 (l : list init_data) :=
match l with
| [] => True
| Init_int8 _ :: l' => is_all_init_int8 l'
| _ => False
end
in let
uninit_int8s := fix uninit_int8s (l: list init_data) :
is_all_init_int8 l -> list int :=
match l with
| [] => fun _ => []
| x :: l' =>
match x with
| Init_int8 i => fun pf => i :: uninit_int8s l' pf
| _ => False_rec (list int)
end
end
in data_at sh (gvar_info v_debruijn)
(map Vint (uninit_int8s (gvar_init v_debruijn) I)) (gv _debruijn).
My final specification is:
Definition secp256k1_ctz64_var_debruijn_spec : ident * funspec :=
DECLARE _secp256k1_ctz64_var_debruijn
WITH a : Z, sh_debruijn : share, gv : globals
PRE [ tulong ]
PROP(0 <= a < Int64.modulus; readable_share sh_debruijn)
PARAMS(Vlong (Int64.repr a))
GLOBALS(gv)
SEP(debruijn64_array sh_debruijn gv)
POST [ tint ]
PROP()
RETURN(Vint (Int.repr (Z.of_nat (ctz a))))
SEP(debruijn64_array sh_debruijn gv).
I know that Javascript Date() function can handle date entry overflows. But in Julia I get Error.
Is there any way to handle overflows automatically?
DateTime(2020, 4, 22, 15, 43, 67) # ----> 2020-4-22T15:44:07
DateTime(2020, 12, 31, 23, 59, 60) # ----> 2021-1-1T00:00:00
I find the default behavior of throwing an error useful. If you want to allow overflows you can define your own function for this eg. like this:
julia> MyDateTime(y, m, d, h, mi, s) =
+(DateTime(0), Year(y), Month(m-1), Day(d-1),
Hour(h), Minute(mi), Second(s))
MyDateTime (generic function with 1 method)
julia> MyDateTime(2020, 4, 22, 15, 43, 67) # ----> 2020-4-22T15:44:07
2020-04-22T15:44:07
julia> MyDateTime(2020, 12, 31, 23, 59, 60) # ----> 2021-1-1T00:00:00
2021-01-01T00:00:00
Note that the order of operations matters there - we first advance year, then month, etc. (as e.g. the effect of advancing time by one second may depend on the month, year and day):
julia> MyDateTime(2020, 2, 28, 23, 59, 60)
2020-02-29T00:00:00
julia> MyDateTime(2021, 2, 28, 23, 59, 60)
2021-03-01T00:00:00
(this can get especially tricky if you have very large and invalid values of month, day etc.)
I have this map
%{
total: 38,
value: 22
}
And would like to add the key :ratio. Is there a way to write immediately:
%{
total: 38,
value: 22,
ratio: __SELF__.value / __SELF__.total
}
or do I need to create another map to achieve this?
Thanks
All data is immutable, so you always have to make a new map.
A simple way, assuming your map is called map:
iex> Map.put(map, :ratio, map.value / map.total)
%{ratio: 0.5789473684210527, total: 38, value: 22}
If you mean that you want to create the map before it already exists, then it would be better to put total and value into variables, and use them to build the map:
defmodule Example do
def make_map(total, value) do
%{total: total, value: value, ratio: value / total}
end
end
iex(1)> Example.make_map(38, 22)
%{ratio: 0.5789473684210527, total: 38, value: 22}
I really wanted to avoid assigning the temporary map to a variable.
Well, because the data at a specific memory location is immutable, elixir can safely use pointers to those memory locations inside new collections. Therefore, creating a temporary variable with intermediate results does not double the amount of memory used. For instance, if you begin with a map that has 1 million entries and you create a new map with one additional entry, you do not use total memory of:
old_map new_map
| |
V V
1 million + ( 1 million + 1)
Rather you only use additional memory of:
new_entry
|
V
1 + pointer_to_old_map
...plus a little extra for the new map's bookkeeping. Like this:
old_map
^
|
new_map = %{ +, a: 10}
Is there a way to write immediately:
%{
total: 38,
value: 22,
ratio: __SELF__.value / __SELF__.total
}
Yes:
%{
total: 38,
value: 22,
ratio: 22/38
}
Now, if you have a list of maps to which you want to add a ratio key:
data = [
%{total: 38, value: 22},
%{total: 40, value: 22},
%{total: 44, value: 22}
]
for %{total: t, value: v}=map <- data do
Map.put(map, :ratio, v/t)
end
output:
[
%{ratio: 0.5789473684210527, total: 38, value: 22},
%{ratio: 0.55, total: 40, value: 22},
%{ratio: 0.5, total: 44, value: 22}
]
After each iteration of the for comprehension, the memory locations of t and v are immediately subject to garbage collection and a pointer to the memory location of map is used in the new map.
I am having an issue in Asterisk 14.6.1 getting my custom CDR fields populated using ODBC to a MySQL database, basically I am making simultaneous outbound calls using Dial and I need to know in the CDRs which phone actually answered the call, so I am using a macro.
So here’s my simple extensions.conf
exten => 12345,1,Dial(PJSIP/071XXXXXXXX#EP&PJSIP/072XXXXXXXX#EP,180,M(test),r)
And my Macro:
[macro-test]
exten => s,1,Verbose(Call Answered from ${CALLERID(num)} to ${DIALEDPEERNUMBER})
exten => s,2,Set(CDR(outboundddi)=${DIALEDPEERNUMBER})
exten => s,3,Set(CDR(userfield)=${DIALEDPEERNUMBER})
So all this works fine, calls are ringing, being answered and macro running!
Output from Asterisk:
PJSIP/PrimaryEP-00000001 answered PJSIP/EP-00000000
– Executing [s#macro-test:1] Verbose(“PJSIP/EP-00000001”, “Call Answered from 12345 to 071XXXXXXXX#EP”) in new stack
Call Answered from 12345 to 071XXXXXXXX#EP
– Executing [s#macro-test:2] Set(“PJSIP/EP-00000001”, “CDR(outboundddi)= 071XXXXXXXX#EP”) in new stack
– Executing [s#macro-test:3] Set(“PJSIP/EP-00000001”, “CDR(userfield)= 071XXXXXXXX#EP”) in new stack
So I know all this works. The Set(CDR(userfield)=${DIALEDPEERNUMBER}) works fine, the Set(CDR(outboundddi)=${DIALEDPEERNUMBER}) does not, it appears to be ignored, and I do not get an error. So the value is getting populated in the userfield of the database, but nothing gets populated in the outboundddi field of the database.
I think it gets ignored because cdr_odbc is registered in the backend as well as cdr_adaptive_odbc - but if I noload cdr_odbc.so then I do not get any CDRs logged in the ODBC database, and if I take out the config in cdr_odbc.conf then again I get nothing on the ODBC database.
Here is some further detail:
cdr show status
Call Detail Record (CDR) settings
Logging: Enabled
Mode: Simple
Log unanswered calls: Yes
Log congestion: Yes
Registered Backends
cdr-custom
cdr_manager (suspended)
radius
Adaptive ODBC
ODBC
res_config_sqlite
odbc show
ODBC DSN Settings
Name: asterisk
DSN: Asterisk
Number of active connections: 1 (out of 1)
module reload cdr_adaptive_odbc.so
Module ‘cdr_adaptive_odbc.so’ reloaded successfully.
– Reloading module ‘cdr_adaptive_odbc.so’ (Adaptive ODBC CDR backend)
== Parsing ‘/etc/asterisk/cdr_adaptive_odbc.conf’: Found
– Found adaptive CDR table cdrs#asterisk.
> Found calldate column with type 93 with len 19, octetlen 19, and numlen (0,10)
> Found clid column with type 12 with len 80, octetlen 80, and numlen (0,0)
> Found src column with type 12 with len 80, octetlen 80, and numlen (0,0)
> Found dst column with type 12 with len 80, octetlen 80, and numlen (0,0)
> Found dcontext column with type 12 with len 80, octetlen 80, and numlen (0,0)
> Found channel column with type 12 with len 80, octetlen 80, and numlen (0,0)
> Found dstchannel column with type 12 with len 80, octetlen 80, and numlen (0,0)
> Found lastapp column with type 12 with len 80, octetlen 80, and numlen (0,0)
> Found lastdata column with type 12 with len 80, octetlen 80, and numlen (0,0)
> Found duration column with type 4 with len 10, octetlen 10, and numlen (0,10)
> Found billsec column with type 4 with len 10, octetlen 10, and numlen (0,10)
> Found disposition column with type 12 with len 45, octetlen 45, and numlen (0,0)
> Found amaflags column with type 4 with len 10, octetlen 10, and numlen (0,10)
> Found accountcode column with type 12 with len 20, octetlen 20, and numlen (0,0)
> Found userfield column with type 12 with len 255, octetlen 255, and numlen (0,0)
> Found uniqueid column with type 12 with len 32, octetlen 32, and numlen (0,0)
> Found linkedid column with type 12 with len 32, octetlen 32, and numlen (0,0)
> Found sequence column with type 12 with len 32, octetlen 32, and numlen (0,0)
> Found peeraccount column with type 12 with len 32, octetlen 32, and numlen (0,0)
> Found outboundddi column with type 12 with len 50, octetlen 50, and numlen (0,0)
cdr_adaptive_cdr.conf
[adaptive_connection]
connection=asterisk
table=cdrs
usegmtime=yes
cdr_odbc.conf
[global]
dsn=asterisk
loguniqueid=yes
dispositionstring=yes
table=cdrs ;“cdr” is default table name
usegmtime=yes ; set to “yes” to log in GMT
hrtime=yes ;Enables microsecond accuracy with the billsec and duration fields
newcdrcolumns=yes ; Enable logging of post-1.8 CDR columns (peeraccount, linkedid, sequence)
I guess I could just forget it and use the userfield that is working, but I’d rather it be stored in a custom CDR field and I’d like to know what is incorrect for my own sanity, so if anyone can point me into what I have configured incorrectly I would be most grateful.
Thanks
David
You have put aliases lines in cdr_adaptive_odbc.conf
alias start => calldate
No, it not scan table itself.
I wrote a max function which takes a Vec as a parameter. It works as I expected. Then I added a min function the same as the max function:
fn main() {
let my_array = vec![61, 14, 71, 23, 42, 8, 13, 66];
let max = max(my_array);
let min = min(my_array);
println!("Max value is {}.", max);
}
fn max(array: Vec<i32>) -> i32 {
let mut max = array[0];
for val in array {
if max < val {
max = val;
}
}
max
}
fn min(array: Vec<i32>) -> i32 {
let mut min = array[0];
for val in array {
if min > val {
min = val;
}
}
min
}
Rust reports an error if I put the same my_array parameter on the call to min:
error[E0382]: use of moved value: `my_array`
--> src/main.rs:4:19
|
2 | let my_array = vec![61, 14, 71, 23, 42, 8, 13, 66];
| -------- move occurs because `my_array` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
3 | let max = max(my_array);
| -------- value moved here
4 | let min = min(my_array);
| ^^^^^^^^ value used here after move
How can I write code that works?
This is an issue that very beginners to Rust will experience. As a beginner, you should read The Rust Programming Language. A lot of effort has been put into this book, especially for newcomers to Rust. This will cover many things that you will run into.
Relevant sections:
Data Types
Understanding Ownership
References and borrowing
The underlying problem is that you've transferred ownership of the vector when you call max. The value is then gone; main no longer has it.
The simplest thing to to is to clone the vector before passing to max. This allows main to keep ownership of my_array and then transfer ownership to min on the subsequent line:
let max = max(my_array.clone());
let min = min(my_array);
This is inefficient, as neither max nor min need to take ownership of the vector to do their work. Cloning the Vec also requires additional memory allocation. It's more idiomatic to pass in a slice, which is a type of reference to the data inside the Vec:
let max = max(&my_array);
let min = min(&my_array);
fn max(array: &[i32]) -> i32 {
let mut max = array[0];
for &val in array {
if max < val {
max = val;
}
}
max
}
When iterating over a slice, you get back references to the items in the slice. With integers, we can dereference them (here using the & in for &val in array) and make a copy of the value.
See also:
Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?
Even better, there's no need to rewrite basic functions like this. You also assume there's always at least one value, which isn't true for an empty vector. The idiomatic solution is to use iterators:
fn main() {
let my_array = vec![61, 14, 71, 23, 42, 8, 13, 66];
let max = my_array.iter().max();
let min = my_array.iter().min();
println!("Max value is {:?}.", max);
println!("Min value is {:?}.", min);
}
This uses Iterator::min and Iterator::max,
which each return an Option, as an empty slice has no minimum or maximum value.
Technically, it's a little different from your original solution, as min and max are Option<&i32>; a reference to the original slice. You can get back to Option<i32> by using Option::copied:
fn main() {
let my_array = vec![61, 14, 71, 23, 42, 8, 13, 66];
let max = my_array.iter().max().copied();
let min = my_array.iter().min().copied();
println!("Max value is {:?}.", max);
println!("Min value is {:?}.", min);
}
Bonus information: slices, Vecs, and arrays are all different types. It's not correct to refer to my_array as an array at all.