I know I’m not always very good at this. Don’t hesitate to contact me if I forgot to mention you here.
thanks to arbipher for reporting (and help debugging) a case of Sdl.open_audio_device failure in WSL2 on Windows https://github.com/sanette/bogue/issues/11
thanks to slegrand45 for debugging black window issue in Chromebook+Debian 11 https://github.com/sanette/bogue/issues/10
thanks to nilsbecker for many tests helping to debug scaling on MacOS retina https://github.com/sanette/bogue/issues/6 and also for reporting badly located config files https://github.com/sanette/bogue/issues/5
thanks to ColMcp for reporting a badly located config file. https://github.com/sanette/bogue/issues/9 and also for https://github.com/sanette/bogue/issues/8
thanks to guygastineau for help on debugging the new installation scheme https://github.com/sanette/bogue/issues/3


this is paragraph :
this is quotation..
Witten by Singh
Visit us at :
Example.com
This is bdo tag
This is bdo tag


|
Context-Free Grammars
|
#include <variable_arity_operator.h>
Public Member Functions | |
| bool | has_no_operands () const |
| int | operand_count () const |
| T & | operand (int index) |
| const T & | operand (int index) const |
| void | add_operand (const T &operand) |
| template<typename TCollection > | |
| void | add_operands (const TCollection &operands) |
| void | replace_operand (int index, const T &operand) |
| void | remove_last_operand () |
| void | clear_operands () |
| void | remove_operands (const std::set< int > &indicesToRemove) |
| bool | operator< (const variable_arity_operator< T > &other) const |
| bool | operator != (const variable_arity_operator< T > &other) const |
| bool | operator== (const variable_arity_operator< T > &other) const |
| virtual | ~variable_arity_operator () |
Protected Member Functions | |
| variable_arity_operator () | |
| variable_arity_operator (const variable_arity_operator< T > &toClone) | |
| variable_arity_operator & | operator= (const variable_arity_operator &toAssign) |
|
inlineprotected |
|
inlineprotected |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inlineprotected |
|
inline |
|
inline |
|
inline |
|
inline |
|
inlinevirtual |


for CIFAR-10 conversion to tensors
copy and paste below when testing
-9,1,2,3,4,5,6,7,8,9,10,11,12,-3,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24
or try this one
-4,1,4,7,10,2,5,8,11,3,6,9,12,-6,21,24,27,210,22,25,28,211,23,26,29,212
This is the set to use
A1,R11,R12,R13,R14,G11,G12,G13,G14,B11,B12,B13,B14,A2,R21,R22,R23,R24,G21,G22,G23,G24,B21,B22,B23,B24


Robot Status
Out of fence, stuck, battery low, idle, mission completed, ...
Battery
Currents
Connections ok
Mission time: elapsed, percent
Pause, Stop, Resume
Mission selector


Start
Options
About
Editor
Music
Sound effects
Show editor (advanced)
Version
By Kasper Höglund
Send levels to<EMAIL_ADDRESS>Game art Mattias Guhl
Additional levels by MM & Rasem
Using
jQuery, Swipe plugin, Move plugin
Howler.js
A*
FileSaver.js
Select World
Name of Set
set name
By set author
Comment set comment
Id set Id
Add Level Edit Level Move Up Move Down Remove Level


|
Boost Sort Parallel
Sorting Algorithms for the Boost Library
|
Classes | |
| struct | range |
| this represent a range between two iterators More... | |
| class | spinlock_t |
| This class implement, from atomic variables, a spinlock. More... | |
| class | stack_cnc |
| This class is a concurrent stack controled by a spin_lock. More... | |
Typedefs | |
| template<class iter_t > | |
| using | compare_iter = std::less< typename iterator_traits< iter_t >::value_type > |
| template<class iter_t > | |
| using | value_iter = typename iterator_traits< iter_t >::value_type |
| template<class T > | |
| using | enable_if_not_integral = typename std::enable_if< !std::is_integral< T >::value >::type |
| template<class T > | |
| using | enable_if_string = typename std::enable_if< std::is_same< T, std::string >::value >::type |
| template<class T > | |
| using | enable_if_not_string = typename std::enable_if<!std::is_same< T, std::string >::value >::type |
Functions | |
| template<typename T > | |
| T | atomic_read (std::atomic< T > &at_var) |
| make the atomic read of an atomic variable, using a memory model More... | |
| template<typename T , typename T2 > | |
| T | atomic_add (std::atomic< T > &at_var, T2 num) |
| Add a number to an atomic variable, using a memory model. More... | |
| template<typename T , typename T2 > | |
| T | atomic_sub (std::atomic< T > &at_var, T2 num) |
| Atomic subtract of an atomic variable using memory model. More... | |
| template<typename T , typename T2 > | |
| void | atomic_write (std::atomic< T > &at_var, T2 num) |
| Write a value in an atomic variable using memory model. More... | |
| template<class Value_t , class... Args> | |
| void | construct (Value_t *ptr, Args &&...args) |
| create an object in the memory specified by ptr More... | |
| template<class Value_t > | |
| void | destroy_object (Value_t *ptr) |
| destroy an object in the memory specified by ptr More... | |
| template<class Iter_t > | |
| void | init (Iter_t first, Iter_t last, typename iterator_traits< Iter_t >::value_type &val) |
| initialize a range of objects with the object val moving across them More... | |
| template<class Iter1_t , class Iter2_t > | |
| Iter2_t | init_move (Iter2_t it_dest, Iter1_t first, Iter1_t last) |
| Move initialized objets. More... | |
| template<class Iter_t , class Value_t = typename iterator_traits< Iter_t >::value_type> | |
| Value_t * | uninit_move (Value_t *ptr, Iter_t first, Iter_t last) |
| Move objets to uninitialized memory. More... | |
| template<class Iter_t > | |
| void | destroy (Iter_t first, const Iter_t last) |
| destroy the elements between first and last More... | |
| template<class Iter1_t , class Iter2_t , class Compare > | |
| Iter2_t | full_merge (Iter1_t buf1, const Iter1_t end_buf1, Iter1_t buf2, const Iter1_t end_buf2, Iter2_t buf_out, Compare comp) |
| Merge two contiguous buffers pointed by buf1 and buf2, and put in the buffer pointed by buf_out. More... | |
| template<class Iter_t , class Value_t , class Compare > | |
| Value_t * | uninit_full_merge (Iter_t first1, const Iter_t last1, Iter_t first2, const Iter_t last2, Value_t *it_out, Compare comp) |
| Merge two contiguous buffers pointed by first1 and first2, and put in the uninitialized buffer pointed by it_out. More... | |
| template<class Iter1_t , class Iter2_t , class Compare > | |
| Iter2_t | half_merge (Iter1_t buf1, const Iter1_t end_buf1, Iter2_t buf2, const Iter2_t end_buf2, Iter2_t buf_out, Compare comp) |
| : Merge two buffers. The first buffer is in a separate memory. The second buffer have a empty space before buf2 of the same size than the (end_buf1 - buf1) More... | |
| template<class Iter1_t , class Iter2_t , class Iter3_t , class Compare > | |
| bool | in_place_merge_uncontiguous (Iter1_t src1, const Iter1_t end_src1, Iter2_t src2, const Iter2_t end_src2, Iter3_t aux, Compare comp) |
| : merge two uncontiguous buffers, placing the results in the buffers Use an auxiliary buffer pointed by aux More... | |
| template<class Iter1_t , class Iter2_t , class Compare > | |
| bool | in_place_merge (Iter1_t src1, Iter1_t src2, Iter1_t end_src2, Iter2_t buf, Compare comp) |
| : merge two contiguous buffers,using an auxiliary buffer pointed by buf. The results are in src1 and src2 More... | |
| template<class Iter_t , class Compare = typename compare_iter< Iter_t >::value_type> | |
| bool | less_range (Iter_t it1, uint32_t pos1, Iter_t it2, uint32_t pos2, Compare comp=Compare()) |
| Compare the elements pointed by it1 and it2, and if they are equals, compare their position, doing a stable comparison. More... | |
| template<class Iter1_t , class Iter2_t , class Compare > | |
| range< Iter1_t > | full_merge4 (const range< Iter1_t > &rdest, range< Iter2_t > vrange_input[4], uint32_t nrange_input, Compare comp) |
| Merge four ranges. More... | |
| template<class Value_t , class Iter_t , class Compare > | |
| range< Value_t * > | uninit_full_merge4 (const range< Value_t * > &dest, range< Iter_t > vrange_input[4], uint32_t nrange_input, Compare comp) |
| Merge four ranges and put the result in uninitialized memory. More... | |
| template<class Iter1_t , class Iter2_t , class Compare > | |
| void | merge_level4 (range< Iter1_t > dest, std::vector< range< Iter2_t > > &v_input, std::vector< range< Iter1_t > > &v_output, Compare comp) |
| merge the ranges in the vector v_input with the full_merge4 function. The v_output vector is used as auxiliary memory in the internal process. The final results is in the dest range. All the ranges of v_output are inside the range dest More... | |
| template<class Value_t , class Iter_t , class Compare > | |
| void | uninit_merge_level4 (range< Value_t * > dest, std::vector< range< Iter_t > > &v_input, std::vector< range< Value_t * > > &v_output, Compare comp) |
| merge the ranges moving the objects and constructing them in uninitialized memory, in the vector v_input using full_merge4. The v_output vector is used as auxiliary memory in the internal process. The final results is in the dest range. All the ranges of v_output are inside the range dest More... | |
| template<class Iter1_t , class Iter2_t , class Compare > | |
| range< Iter2_t > | merge_vector4 (range< Iter1_t > range_input, range< Iter2_t > range_output, std::vector< range< Iter1_t > > &v_input, std::vector< range< Iter2_t > > &v_output, Compare comp) |
| merge the ranges in the vector v_input using the merge_level4 function. The v_output vector is used as auxiliary memory in the internal process The final results is in the range_output range. All the ranges of v_output are inside the range range_output All the ranges of v_input are inside the range range_input More... | |
| template<class Iter_t > | |
| range< Iter_t > | concat (const range< Iter_t > &it1, const range< Iter_t > &it2) |
| concatenate two contiguous ranges More... | |
| template<class Iter1_t , class Iter2_t > | |
| range< Iter2_t > | init_move (const range< Iter2_t > &dest, const range< Iter1_t > &src) |
| Move initialized objets from the range src to dest. More... | |
| template<class Iter1_t , class Iter2_t > | |
| range< Iter2_t > | uninit_move (const range< Iter2_t > &dest, const range< Iter1_t > &src) |
| Move uninitialized objets from the range src creating them in dest. More... | |
| template<class Iter_t > | |
| void | destroy (range< Iter_t > rng) |
| destroy a range of objects More... | |
| template<class Iter_t > | |
| range< Iter_t > | init (const range< Iter_t > &rng, typename iterator_traits< Iter_t >::value_type &val) |
| initialize a range of objects with the object val moving across them More... | |
| template<class Iter1_t , class Iter2_t , class Compare > | |
| bool | is_mergeable (const range< Iter1_t > &src1, const range< Iter2_t > &src2, Compare comp) |
| : indicate if two ranges have a possible merge More... | |
| template<class Iter1_t , class Iter2_t , class Iter3_t , class Compare > | |
| range< Iter3_t > | full_merge (const range< Iter3_t > &dest, const range< Iter1_t > &src1, const range< Iter2_t > &src2, Compare comp) |
| Merge two contiguous ranges src1 and src2, and put the result in the range dest, returning the range merged. More... | |
| template<class Iter1_t , class Iter2_t , class Value_t , class Compare > | |
| range< Value_t * > | uninit_full_merge (const range< Value_t * > &dest, const range< Iter1_t > &src1, const range< Iter2_t > &src2, Compare comp) |
| Merge two contiguous uninitialized ranges src1 and src2, and create and move the result in the uninitialized range dest, returning the range merged. More... | |
| template<class Iter1_t , class Iter2_t , class Compare > | |
| range< Iter2_t > | half_merge (const range< Iter2_t > &dest, const range< Iter1_t > &src1, const range< Iter2_t > &src2, Compare comp) |
| : Merge two initialized buffers. The first buffer is in a separate memory More... | |
| template<class Iter1_t , class Iter2_t , class Iter3_t , class Compare > | |
| bool | in_place_merge_uncontiguous (const range< Iter1_t > &src1, const range< Iter2_t > &src2, const range< Iter3_t > &aux, Compare comp) |
| : merge two non contiguous ranges src1, src2, using the range aux as auxiliary memory. The results are in the original ranges More... | |
| template<class Iter1_t , class Iter2_t , class Compare > | |
| range< Iter1_t > | in_place_merge (const range< Iter1_t > &src1, const range< Iter1_t > &src2, const range< Iter2_t > &buf, Compare comp) |
| : merge two contiguous ranges ( src1, src2) using buf as auxiliary memory. The results are in the same ranges More... | |
| template<class Iter1_t , class Iter2_t , class Compare > | |
| void | merge_flow (range< Iter1_t > rng1, range< Iter2_t > rbuf, range< Iter1_t > rng2, Compare cmp) |
| : merge two ranges, as part of a merge the ranges in a list. This function reduce the number of movements compared with inplace_merge when you need to merge a sequence of ranges. This function merge the ranges rbuf and rng2, and the results are in rng1 and rbuf More... | |
| using boost::sort::parallel::detail::util::compare_iter = typedef std::less< typename iterator_traits< iter_t >::value_type > |
| using boost::sort::parallel::detail::util::enable_if_not_integral = typedef typename std::enable_if< !std::is_integral< T >::value >::type |
| using boost::sort::parallel::detail::util::enable_if_not_string = typedef typename std::enable_if<! std::is_same< T, std::string >::value >::type |
| using boost::sort::parallel::detail::util::enable_if_string = typedef typename std::enable_if< std::is_same< T, std::string >::value >::type |
| using boost::sort::parallel::detail::util::value_iter = typedef typename iterator_traits< iter_t >::value_type |
|
inline |
Add a number to an atomic variable, using a memory model.
| at_var | : variable to add |
| num | : value to add to at_var |
|
inline |
make the atomic read of an atomic variable, using a memory model
| at_var | : atomic variable to read |
|
inline |
Atomic subtract of an atomic variable using memory model.
| at_var | : Varibale to subtract |
| num | : value to sub to at_var |
|
inline |
Write a value in an atomic variable using memory model.
| at_var | : varible to write |
| num | : value to write in at_var |
| range< Iter_t > boost::sort::parallel::detail::util::concat | ( | const range< Iter_t > & | it1, |
| const range< Iter_t > & | it2 | ||
| ) |
concatenate two contiguous ranges
| it1 | : first range |
| it2 | : second range |
|
inline |
create an object in the memory specified by ptr
| ptr | : pointer to the memory where to create the object |
| args | : arguments to the constructor |
| void boost::sort::parallel::detail::util::destroy | ( | Iter_t | first, |
| const Iter_t | last | ||
| ) |
destroy the elements between first and last
| first | : iterator to the first element to destroy |
| last | : iterator to the last element to destroy |
|
inline |
destroy a range of objects
| rng | : range to destroy |
|
inline |
destroy an object in the memory specified by ptr
| ptr | : pointer to the object to destroy |
| Iter2_t boost::sort::parallel::detail::util::full_merge | ( | Iter1_t | buf1, |
| const Iter1_t | end_buf1, | ||
| Iter1_t | buf2, | ||
| const Iter1_t | end_buf2, | ||
| Iter2_t | buf_out, | ||
| Compare | comp | ||
| ) |
Merge two contiguous buffers pointed by buf1 and buf2, and put in the buffer pointed by buf_out.
| buf1 | : iterator to the first element in the first buffer |
| end_buf1 | : final iterator of first buffer |
| buf2 | : iterator to the first iterator to the second buffer |
| end_buf2 | : final iterator of the second buffer |
| buf_out | : buffer where move the elements merged |
| comp | : comparison object |
|
inline |
Merge two contiguous ranges src1 and src2, and put the result in the range dest, returning the range merged.
| dest | : range where locate the lements merged. the size of dest must be greater or equal than the sum of the sizes of src1 and src2 |
| src1 | : first range to merge |
| src2 | : second range to merge |
| comp | : comparison object |
| range< Iter1_t > boost::sort::parallel::detail::util::full_merge4 | ( | const range< Iter1_t > & | rdest, |
| range< Iter2_t > | vrange_input[4], | ||
| uint32_t | nrange_input, | ||
| Compare | comp | ||
| ) |
Merge four ranges.
| dest | range where move the elements merged. Their size must be greater or equal than the sum of the sizes of the ranges in vrange_input |
| vrange_input | : array of ranges to merge |
| nrange_input | : number of ranges in vrange_input |
| comp | : comparison object |
| Iter2_t boost::sort::parallel::detail::util::half_merge | ( | Iter1_t | buf1, |
| const Iter1_t | end_buf1, | ||
| Iter2_t | buf2, | ||
| const Iter2_t | end_buf2, | ||
| Iter2_t | buf_out, | ||
| Compare | comp | ||
| ) |
: Merge two buffers. The first buffer is in a separate memory. The second buffer have a empty space before buf2 of the same size than the (end_buf1 - buf1)
| buf1 | : iterator to the first element of the first buffer |
| end_buf1 | : iterator to the last element of the first buffer |
| buf2 | : iterator to the first element of the second buffer |
| end_buf2 | : iterator to the last element of the second buffer |
| buf_out | : iterator to the first element to the buffer where put the result |
| comp | : object for Compare two elements of the type pointed by the Iter1_t and Iter2_t |
|
inline |
: Merge two initialized buffers. The first buffer is in a separate memory
| dest | : range where finish the two buffers merged |
| src1 | : first range to merge in a separate memory |
| src2 | : second range to merge, in the final part of the range where deposit the final results |
| comp | : object for compare two elements of the type pointed by the Iter1_t and Iter2_t |
| bool boost::sort::parallel::detail::util::in_place_merge | ( | Iter1_t | src1, |
| Iter1_t | src2, | ||
| Iter1_t | end_src2, | ||
| Iter2_t | buf, | ||
| Compare | comp | ||
| ) |
: merge two contiguous buffers,using an auxiliary buffer pointed by buf. The results are in src1 and src2
| src1 | iterator to the first position of the first buffer |
| src2 | final iterator of the first buffer and first iterator of the second buffer |
| end_src2 | : final iterator of the second buffer |
| buf | : iterator to buffer used as auxiliary memory |
| comp | : object for to Compare elements |
|
inline |
: merge two contiguous ranges ( src1, src2) using buf as auxiliary memory. The results are in the same ranges
| src1 | : first range to merge |
| src1 | : second range to merge |
| buf | : auxiliary memory used in the merge |
| comp | : object for to compare elements |
| bool boost::sort::parallel::detail::util::in_place_merge_uncontiguous | ( | Iter1_t | src1, |
| const Iter1_t | end_src1, | ||
| Iter2_t | src2, | ||
| const Iter2_t | end_src2, | ||
| Iter3_t | aux, | ||
| Compare | comp | ||
| ) |
: merge two uncontiguous buffers, placing the results in the buffers Use an auxiliary buffer pointed by aux
| src1 | : iterator to the first element of the first buffer |
| end_src1 | : last iterator of the first buffer |
| src2 | : iterator to the first element of the second buffer |
| end_src2 | : last iterator of the second buffer |
| aux | : iterator to the first element of the auxiliary buffer |
| comp | : object for to Compare elements |
|
inline |
: merge two non contiguous ranges src1, src2, using the range aux as auxiliary memory. The results are in the original ranges
| src1 | : first range to merge |
| src2 | : second range to merge |
| aux | : auxiliary range used in the merge |
| comp | : object for to compare elements |
| void boost::sort::parallel::detail::util::init | ( | Iter_t | first, |
| Iter_t | last, | ||
| typename iterator_traits< Iter_t >::value_type & | val | ||
| ) |
initialize a range of objects with the object val moving across them
| first | : itertor to the first element to initialize |
| last | : iterator to the last element to initialize |
| val | : object used for the initialization |
|
inline |
initialize a range of objects with the object val moving across them
| rng | : range of elements not initialized |
| val | : object used for the initialization |
| Iter2_t boost::sort::parallel::detail::util::init_move | ( | Iter2_t | it_dest, |
| Iter1_t | first, | ||
| Iter1_t | last | ||
| ) |
Move initialized objets.
| it_dest | : iterator to the final place of the objects |
| first | : iterator to the first element to move |
| last | : iterator to the last element to move |
|
inline |
Move initialized objets from the range src to dest.
| dest | : range where move the objects |
| src | : range from where move the objects |
|
inline |
: indicate if two ranges have a possible merge
| src1 | : first range |
| src2 | : second range |
| comp | : object for to compare elements |
|
inline |
Compare the elements pointed by it1 and it2, and if they are equals, compare their position, doing a stable comparison.
| it1 | : iterator to the first element |
| pos1 | : position of the object pointed by it1 |
| it2 | : iterator to the second element |
| pos2 | : position of the element pointed by it2 |
| comp | : comparison object |
| void boost::sort::parallel::detail::util::merge_flow | ( | range< Iter1_t > | rng1, |
| range< Iter2_t > | rbuf, | ||
| range< Iter1_t > | rng2, | ||
| Compare | cmp | ||
| ) |
: merge two ranges, as part of a merge the ranges in a list. This function reduce the number of movements compared with inplace_merge when you need to merge a sequence of ranges. This function merge the ranges rbuf and rng2, and the results are in rng1 and rbuf
| rng1 | : range where locate the first elements of the merge |
| rbuf | : range which provide the first elements, and where store the last results of the merge |
| rng2 | : range which provide the last elements to merge |
| comp | : object for to compare elements |
| void boost::sort::parallel::detail::util::merge_level4 | ( | range< Iter1_t > | dest, |
| std::vector< range< Iter2_t > > & | v_input, | ||
| std::vector< range< Iter1_t > > & | v_output, | ||
| Compare | comp | ||
| ) |
merge the ranges in the vector v_input with the full_merge4 function. The v_output vector is used as auxiliary memory in the internal process. The final results is in the dest range. All the ranges of v_output are inside the range dest
| dest | : range where move the elements merged |
| v_input | : vector of ranges to merge |
| v_output | : vector of ranges obtained |
| comp | : comparison object |
| range< Iter2_t > boost::sort::parallel::detail::util::merge_vector4 | ( | range< Iter1_t > | range_input, |
| range< Iter2_t > | range_output, | ||
| std::vector< range< Iter1_t > > & | v_input, | ||
| std::vector< range< Iter2_t > > & | v_output, | ||
| Compare | comp | ||
| ) |
merge the ranges in the vector v_input using the merge_level4 function. The v_output vector is used as auxiliary memory in the internal process The final results is in the range_output range. All the ranges of v_output are inside the range range_output All the ranges of v_input are inside the range range_input
| range_input | : range including all the ranges of v_input |
| ange_output | : range including all the elements of v_output |
| v_input | : vector of ranges to merge |
| v_output | : vector of ranges obtained |
| comp | : comparison object |
| Value_t* boost::sort::parallel::detail::util::uninit_full_merge | ( | Iter_t | first1, |
| const Iter_t | last1, | ||
| Iter_t | first2, | ||
| const Iter_t | last2, | ||
| Value_t * | it_out, | ||
| Compare | comp | ||
| ) |
Merge two contiguous buffers pointed by first1 and first2, and put in the uninitialized buffer pointed by it_out.
| first1 | : iterator to the first element in the first buffer |
| last1 | : last iterator of the first buffer |
| first2 | : iterator to the first element to the second buffer |
| last2 | : final iterator of the second buffer |
| it_out | : uninitialized buffer where move the elements merged |
| comp | : comparison object |
|
inline |
Merge two contiguous uninitialized ranges src1 and src2, and create and move the result in the uninitialized range dest, returning the range merged.
| dest | : range where locate the elements merged. the size of dest must be greater or equal than the sum of the sizes of src1 and src2. Initially is uninitialize memory |
| src1 | : first range to merge |
| src2 | : second range to merge |
| comp | : comparison object |
| range< Value_t * > boost::sort::parallel::detail::util::uninit_full_merge4 | ( | const range< Value_t * > & | dest, |
| range< Iter_t > | vrange_input[4], | ||
| uint32_t | nrange_input, | ||
| Compare | comp | ||
| ) |
Merge four ranges and put the result in uninitialized memory.
| dest | range where create and move the elements merged. Their size must be greater or equal than the sum of the sizes of the ranges in the array R |
| vrange_input | : array of ranges to merge |
| nrange_input | : number of ranges in vrange_input |
| comp | : comparison object |
| void boost::sort::parallel::detail::util::uninit_merge_level4 | ( | range< Value_t * > | dest, |
| std::vector< range< Iter_t > > & | v_input, | ||
| std::vector< range< Value_t * > > & | v_output, | ||
| Compare | comp | ||
| ) |
merge the ranges moving the objects and constructing them in uninitialized memory, in the vector v_input using full_merge4. The v_output vector is used as auxiliary memory in the internal process. The final results is in the dest range. All the ranges of v_output are inside the range dest
| dest | : range where move the elements merged |
| v_input | : vector of ranges to merge |
| v_output | : vector of ranges obtained |
| comp | : comparison object |
| Value_t* boost::sort::parallel::detail::util::uninit_move | ( | Value_t * | ptr, |
| Iter_t | first, | ||
| Iter_t | last | ||
| ) |
Move objets to uninitialized memory.
| ptr | : pointer to the memory where to create the objects |
| first | : iterator to the first element to move |
| last | : iterator to the last element to move |
|
inline |
Move uninitialized objets from the range src creating them in dest.
| dest | : range where move and create the objects |
| src | : range from where move the objects |


stdio_ext
,__fbufsize
,__fpending
,__flbf
,__freadable
,__fwritable
,__freading
,__fwriting
—access internals of FILE structureSynopsis
#include <stdio.h> #include <stdio_ext.h> size_t __fbufsize(FILE *fp); size_t __fpending(FILE *fp); int __flbf(FILE *fp); int __freadable(FILE *fp); int __fwritable(FILE *fp); int __freading(FILE *fp); int __fwriting(FILE *fp);
Description
These functions provides access to the internals of the FILE structure fp.
Returns
__fbufsize
returns the number of bytes in the buffer of stream fp.
__fpending
returns the number of bytes in the output buffer of stream fp.
__flbf
returns nonzero if stream fp is line-buffered, and 0
if not.
__freadable
returns nonzero if stream fp may be read, and 0
if not.
__fwritable
returns nonzero if stream fp may be written, and 0
if not.
__freading
returns nonzero if stream fp if the last operation on
it was a read, or if it read-only, and 0
if not.
__fwriting
returns nonzero if stream fp if the last operation on
it was a write, or if it write-only, and 0
if not.
Portability
These functions originate from Solaris and are also provided by GNU libc.
No supporting OS subroutines are required.


Buffalo City: SA's rarest tourist bouquet | IOL News
The end of year holiday season is finally upon us. Two weeks from now, traffic volumes on the roads, railway lines and the air space will increase exponentially with teeming multitudes headed for different destinations for much deserved rest, play, reflection and reconnection with long-seen friends and loved ones.
Far from the expected oaths of a patriotic national, our country, South Africa, is endowed with unique natural and human-made spaces for any of these pursuits.
Consider our agreeable weather during this period – for the most part sunny with occasional rain in some parts of the country – our diverse flora and fauna, the roaring seas, majestic mountains, hills and plains, and the many historical sites that bear witness to the titanic struggle that was the midwife of our freedom.
Very few countries on earth boast such congenial mix and diversity; more so during the summer season. Which is not, of course, to suggest any notion of South African exceptionalism.
Fewer places exemplify the country’s diverse scenic beauty, rich history and under-explored tourist offering and potential than the 2 536 km 2 area of the Buffalo City Metropolitan City which lies on the east coast of the Eastern Cape Province. Little explored by fellow nationals and citizens from the rest of the world, Buffalo City is arguably one of South Africa’s rarest tourist bouquets.


--- title: Last Words from Death Row author: Kathryn Daugherty date: '2017-11-25' slug: last-words-from-death-row categories: [] tags: [] css: [] description: '' highlight: yes scripts: [] ---
A Kaggle data source here provides the public with information on Texas death row inmates from 1982 to 2017. It includes name, age, race, county, date, and last words from each person. We will analyze this using R to conduct text analysis.
Let’s load up tidytext to get started and then pull in the text data file.
# Set up tidytext
require(tidytext)
# Set working directory
setwd("~/Desktop/R/TX_Executions/text/")
# Load dataset
offenders <- read.table("Last_Statement.txt")
# offenders <- readLines(file.choose())
head(offenders)
Next, we’re going to load additional libraries and convert the text document into a text corpus.
# Load other packages
require(dplyr)
require(ggplot2)
require(wordcloud)
require(stringr)
require(tm)
require(SnowballC)
require(RColorBrewer)
# Convert text to corpus
lastWords <- Corpus(VectorSource(offenders))
Text analysis often requires a fair amount of processing. We’ll do that here.
# Clean up text
toSpace <- content_transformer(function (x , pattern ) gsub(pattern, " ", x))
lastWords <- tm_map(lastWords, toSpace, "/")
lastWords <- tm_map(lastWords, toSpace, "@")
lastWords <- tm_map(lastWords, toSpace, "\\|")
lastWords <- tm_map(lastWords, toSpace, "\x89")
lastWords <- tm_map(lastWords, toSpace, "xdb")
lastWords <- tm_map(lastWords, toSpace, "xcf")
lastWords <- tm_map(lastWords, toSpace, "xe5")
lastWords <- tm_map(lastWords, toSpace, "xca")
# Convert the text to lower case
lastWords <- tm_map(lastWords, content_transformer(tolower))
# Remove numbers
lastWords <- tm_map(lastWords, removeNumbers)
# Remove english common stopwords
lastWords <- tm_map(lastWords, removeWords, stopwords("english"))
# Remove punctuations
lastWords <- tm_map(lastWords, removePunctuation)
# Eliminate extra white spaces
lastWords <- tm_map(lastWords, stripWhitespace)
With the cleaned-up text, we’ll want to create a term document matrix (TDM).
# Construct term document matrix
dtm <- TermDocumentMatrix(lastWords)
m <- as.matrix(dtm)
v <- sort(rowSums(m),decreasing=TRUE)
d <- data.frame(word = names(v),freq=v)
head(d, 10)
Now, we’re in a spot where we can start to analyze the data-set. We’re going to create a word cloud that shows the 75 most frequently used words (while also ensuring each word shown is used at least 20 times).
# Create word cloud
set.seed(1234)
wordcloud(words = d$word, freq = d$freq, min.freq = 20,
max.words=75, random.order=FALSE, rot.per=0.00,
colors=brewer.pal(4, "RdGy"))
We see that love stands out. There are other themes such as religion (faith, god, jesus, lord and christ) and remorse (forgive, pain and sorry).
To simplify this further, we can construct a bar chart that shows the top fifteen words used.
# Plot word frequencies
# Bar chart
barplot(d[1:15,]$freq, las = 2, names.arg = d[1:15,]$word,
col ="grey", main ="Most Spoken Last Words",
ylab = "Frequency")
This shows the same information as the word cloud, but defines the rank and order with more detail.
[THE END]


Soldier Plenos:
Welcome to Keucereus Alliance Base. We need all the soldiers we can get.
Your missions here will be mainly in the sky. My advice is to obtain an Airship, but I see some adventurers from Aden also fight using their ability of transformation.
Go ask Engineer Lekon about which method is best for you. If you want to know about our enemy, talk to Admiral Keucereus or General Dilios.
Quest


The internet was missing the ability to provide custom-sized placeholder images of Steven Segal. Now it can.
Calm: https://stevensegallery.com/200/300
Gray: https://stevensegallery.com/g/200/300


Scott Doyle /<EMAIL_ADDRESS>Core assertion in model-building and parameter estimation: Values of a random variable are observed according to a known probability law.
“Randomness” refers to the unpredictable variations in an observed value.
These variations can occur with a specific, pre-determined likelihood – the probability law.
The probability law (i.e. distribution) is known or assumed.
This distribution governs the general pattern of observed variations.
We can estimate the parameters of the distribution (denoted $\boldsymbol{\theta}$).
Maximum Likelihood Estimation (MLE)
Bayesian Estimation (BAY)
Our sample-size-dependent estimation of parameters:
\begin{align} \mu_{n} &= \left( \frac{n\sigma_{0}^{2}}{n\sigma_{0}^{2} + \sigma^{2}} \right) \widehat{\mu}_{n} + \frac{ \sigma^{2} }{ n\sigma_{0}^{2} + \sigma^{2} } \mu_{0} \\ \sigma_{n}^{2} &= \frac{ \sigma_{0}^{2} \sigma^{2} }{ n\sigma_{0}^{2} + \sigma^{2} } \end{align}
If $\sigma_{n}^{2}$ is our “uncertainty”, as $n \rightarrow \infty$, our uncertainty goes towards zero: More samples means less uncertainty.
If $\mu_{n}$ is our “best guess”, as $n \rightarrow \infty$, it is a linear combination of $\widehat{\mu}_{n}$ (the sample mean) and $\mu_{0}$ (our best prior guess for $\mu$).
As long as $\sigma_{0}^{2} \neq 0$, then $\mu_{n}$ approaches the sample mean as $n \rightarrow \infty$.
The core assumption for parametric techniques relies on a known parameterized probability law.
What if we have no idea what model governs our sample values, or if our model is a poor match for our samples?
In other words, we either have no model or a poorly fit model.
We will examine a few nonparametric techniques, where we assume essentially “arbitrary distributions” (those without a form) or unknown distributions.
Recall our training: $\mathcal{D} = \{x_{1}, \ldots, x_{N}\}$.
Our goal is to model $p(x)$ from $\mathcal{D}$.
In a nonparametric setting, we can choose a bin size, $\Delta_{i}$, and count the number of points falling into bin $i$.
To convert into a normalized density, divide by the total number of observations $N$ and the width $\Delta_{i}$:
$p_{i} = \frac{ n_{i} }{ N\Delta_{i} } $
Hence, the model for the density is constant over each bin (typically all $\Delta_{i}$ are equal).

It’s hard to select $\Delta$ properly.
Remember: $N$ is often small, and we don’t know the real distribution.
We can continuously estimate $p(x)$ as we collect training.
Binning introduces discontinuities at the edges of the bin, and scales poorly as the dimensionality increases.
Thus we should do the following:
The process of calculating the density across a region is known as density estimation.
Just as we did with the histograms, we assume that our sample values fall within some region $\mathcal{R}$; the probability that a point falls within $\mathcal{R}$ is:
$ P = \int_{\mathcal{R}} p(\mathbf{x}^{\prime}) d\mathbf{x}^{\prime} $
If we observe $n$ samples, then the probability that $k$ fall within $\mathcal{R}$ is given by the binomial distribution:
$ P_{k} = {n \choose k} P^{k} (1 - P)^{n - k}, \qquad {n \choose k} = \frac{ n! }{ k!(n - k)!} $
And the expected value of $k$ is thus:
$ \mathcal{E}[k] = nP $
$P_{k}$ peaks sharply around the mean, so we expect that $k/n$ is a pretty good estimate of $P$.
This estimate gets more and more accurate as $n$ increases (i.e. as we observe more samples).
If we assume that $p(\mathbf{x})$ is continuous and $\mathcal{R}$ is really small so $p(\mathbf{x})$ does not vary appreciably within it, then we have:
$ \int_{\mathcal{R}} p(\mathbf{x}^{\prime}) d\mathbf{x}^{\prime} \simeq p(\mathbf{x})V $
$V$ is the volume enclosed by $\mathcal{R}$.
We combine the previous equations to get:
$ p(\mathbf{x}) \simeq \frac{ k/n }{ V } $
However, this leaves some problems.
We said that $\mathcal{R}$ is small, so $p(\mathbf{x})$ doesn’t vary, but it should be large enough that the number of points falling inside it yields a sharply peaked binomial.
We can fix the volume $V$ and increase the number of training samples, but this will only yield an estimate of the space-averaged density $P/V$ (we want the actual $P$).
Also, since $V$ is the space enclosed by $\mathcal{R}$, if it is TOO small, then no points will fall inside it and we’ll end up with $p(\mathbf{x}) \simeq 0$.
So let’s start by assuming we have an infinite number of samples.
To estimate the density at $\mathbf{x}$, first form a sequence of regions $\mathcal{R}_{1}, \mathcal{R}_{2}, \ldots$ where $\mathcal{R}_{1}$ contains 1 sample, $\mathcal{R}_{2}$ contains two, and so on.
We can write $V_{n}$ as the volume of $\mathcal{R}_{n}$, and $k_{n}$ is the number of samples falling in $\mathcal{R}_{n}$:
$ p_{n}(\mathbf{x}) = \frac{ k_{n} / n }{ V_{n} } = \frac{ k_{n} }{ nV_{n} } $
As $n \rightarrow \infty$, we want $p_{n}(\mathbf{x})$ (the density dependent on our sample size) to converge to $p(\mathbf{x})$ (the true density around $\mathbf{x}$).
For this to happen, we must satisfy a few conditions as $n \rightarrow \infty$.
$ p_{n}(\mathbf{x}) = \frac{ k_{n} }{ nV_{n} } $
Here are our conditions:
So how do we build a region that specifies these conditions?
Parzen Windows: Shrink a region by specifying volume $V_{n}$ as a function of $n$, such as $V_{n} = 1/\sqrt{n}$. Then, we’ll show that $p_{n}(\mathbf{x})$ converges to $p(\mathbf{x})$.
K-Nearest Neighbor: Specify $k_{n}$ as a function of $n$, such as $k_{n} = \sqrt{n}$. Then, the volume $V_{n}$ is grown until it encloses $k_{n}$ neighbors of $\mathbf{x}$.
Both of these methods converge (of course, as $n\rightarrow\infty$).
Let’s start by assuming the region $\mathcal{R}$ is a $d$-dimensional hypercube, with $h_{n}$ being the length of an edge. Thus the volume is given by:
$ V_{n} = h_{n}^{d} $
We can obtain an analytic expression for $k_{n}$, the number of samples falling in the hypercube, by defining a window function:
$ \varphi(\mathbf{u}) = \begin{cases} 1 & \quad |u_{j}| \leq 1/2 \quad \forall j \\ 0 & \quad \text{otherwise} \end{cases} $
This function defines a unit hypercube centered at the origin.
$ \varphi(\mathbf{u}) = \begin{cases} 1 & \quad |u_{j}| \leq 1/2 \quad \forall j \\ 0 & \quad \text{otherwise} \end{cases} $
We can see that if $\mathbf{u} = (\mathbf{x} - \mathbf{x}_{i})/h_{n}$, then $\varphi(\mathbf{u})$ is equal to 1 if $\mathbf{x}_{i}$ falls within the hypercube of volume $V_{n}$ centered at $\mathbf{x}$, and is zero otherwise.
The number of samples in the hypercube is given by:
$ k_{n} = \sum_{i=1}^{n} \varphi\left(\frac{\mathbf{x} - \mathbf{x}_{i}}{ h_{n} } \right) $
Recall that $p_{n}(\mathbf{x}) = \frac{ k_{n} }{ nV_{n} }$, so we get:
$ p_{n}(\mathbf{x}) = \frac{ 1 }{ n } \sum_{i=1}^{n} \frac{ 1 }{ V_{n} } \varphi \left( \frac{ \mathbf{x} - \mathbf{x}_{i} }{ h_{n} } \right) $
$ p_{n}(\mathbf{x}) = \frac{ 1 }{ n } \sum_{i=1}^{n} \frac{ 1 }{ V_{n} } \varphi \left( \frac{ \mathbf{x} - \mathbf{x}_{i} }{ h_{n} } \right) $
We can make $\varphi$ – the Parzen window function – to be any function of $\mathbf{x}$, controlling how to weight samples in $\mathcal{D}$ to determine $p(\mathbf{x})$ at a specific $\mathbf{x}$.
The equation for $p_{n}(\mathbf{x})$ is an average of functions of $\mathbf{x}$ and $\mathbf{x}_{i}$.
Thus the window function is being used for interpolation.
We can ensure the density is “regular” (non-negative, sums to 1) by the conditions:
$ \varphi(\mathbf{x}) \geq 0 $
$ \int \varphi(\mathbf{u}) d\mathbf{u} = 1 $
As before, we must consider the effect of the window width $h_{n}$ on $p_{n}(\mathbf{x})$.
Define the function:
$ \delta_{n}(\mathbf{x}) = \frac{ 1 }{ V_{n} } \varphi\left(\frac{ \mathbf{x} }{ h_{n} } \right) $
Substituting this into our equation for the density, we get:
$ p_{n}(\mathbf{x}) = \frac{ 1 }{ n } \sum_{i=1}^{n} \delta_{n}( \mathbf{x} - \mathbf{x}_{i} ) $
Since $V_{n} = h_{n}^{d}$, the width $h_{n}$ clearly affects both the amplitude and the width of $\delta_{n}(\mathbf{x})$.
The relationship between $h_{n}$ and the amplitude of $\delta_{n}$ is inverse.
If $h_{n}$ is large, then the amplitude of $\delta_{n}$ is small, and $\mathbf{x}$ must be far from $\mathbf{x}_{i}$ before $\delta_{n}( \mathbf{x} - \mathbf{x}_{i})$ deviates from $\delta_{n}(\mathbf{0})$.
If $h_{n}$ is small, then the peak value of $\delta_{n}(\mathbf{x} - \mathbf{x}_{i})$ is large and occurs close to $\mathbf{x} = \mathbf{x}_{i}$ (i.e. $\delta_{n}(\mathbf{0})$).
The relationship between $h_{n}$ and the amplitude of $\delta_{n}$ is inverse.
If $h_{n}$ is large, then the amplitude of $\delta_{n}$ is small, and $\mathbf{x}$ must be far from $\mathbf{x}_{i}$ before $\delta_{n}( \mathbf{x} - \mathbf{x}_{i})$ deviates from $\delta_{n}(\mathbf{0})$.
If $h_{n}$ is small, then the peak value of $\delta_{n}(\mathbf{x} - \mathbf{x}_{i})$ is large and occurs close to $\mathbf{x} = \mathbf{x}_{i}$ (i.e. $\delta_{n}(\mathbf{0})$).
For any value of $h_{n}$, the distribution is normalized:
$ \int \delta_{n}(\mathbf{x} - \mathbf{x}_{i}) d\mathbf{x} = \int \frac{ 1 }{ V_{n} } \varphi\left( \frac{ \mathbf{x} - \mathbf{x}_{i} }{ h_{n} } \right) d\mathbf{x} = \int \varphi(\mathbf{u})d\mathbf{u} = 1 $
This means that as $h_{n}$ gets smaller and smaller, $\delta_{n}(\mathbf{x} - \mathbf{x}_{i})$ approaches a Dirac delta function centered at $\mathbf{x}_{i}$, and $p_{n}(\mathbf{x})$ approaches a superposition of deltas centered at the samples.
When that happens, you’ll need more and more samples to approximate the true distribution of $p(\mathbf{x})$!
If you get confused about the densities, think in terms of building a histogram.
You want to know how many samples fall within each range of x-values.
You have to choose the bin width parameter to properly reveal the underlying distribution.
Having more samples will lead you to a better estimation of the density; an infinite number of samples will lead to a perfect estimation (convergence).
This is a simple method, but without much else to go on, it may give you a good way of looking at your data.
K-Nearest Neighbor: Specify $k_{n}$ as a function of $n$, such as $k_{n} = \sqrt{n}$. Then, the volume $V_{n}$ is grown until it encloses $k_{n}$ neighbors of $\mathbf{x}$.
Selecting the window size is typically done \textit{ad hoc}.
Instead of picking a window size and then seeing how the data fits, why not use the training data to dictate the size of the window?
K-NN allows the window size to be a function of observed samples:
If density is high, then the window is small – high resolution.
If density is low, then the window is large (but stops at an appropriate size).
$ p_{n}(\mathbf{x}) = \frac{ k_{n} }{ nV_{n} } $
Recall our convergence discussion from last time…
We want $\lim_{n\rightarrow\infty}{k_{n}} = \infty$, assuring that $k_{n}/n$ will estimate $p_{n}(\mathbf{x})$.
We also want $\lim_{n\rightarrow\infty}{k_{n}/n} = 0$, ensuring $k_{n}$ grows more slowly than $n$.
These conditions ensure that $p_{n}(\mathbf{x})$ converges to $p(\mathbf{x})$.
If $n=1$ and $k_{n} = \sqrt{n} = 1$, our estimate becomes:
$ p_{n}(\mathbf{x}) = \frac{ 1 }{ 2 |x - x_{1}|} $
This diverges (as opposed to converging) to infinity – so it’s a poor estimate of $p(\mathbf{x})$.
However, the density never reaches 0 in the finite-sample case, because instead of defining the density by some arbitrary window, we define it by the nearest possible values of the random variable (which is always nonzero).
Since $n$ never actually reaches infinity, this is an okay tradeoff in most scenarios.
We saw in Parzen windows we had to choose the width carefully so that we generalized well without overfitting.
Here, we select $k_{n}$, e.g. the number of neighbors we use to grow the region to reach.
When training is limited, $k_{n}$ can drastically alter the form of the density.
As with everything else, the choice of $k_{n}$ is done based on what gives the best results (which can be evaluated in terms of classifier accuracy).
We can directly estimate the posterior probabilities $P(\omega_{i} | \mathbf{x})$ from a set of $n$ labeled samples by using them to estimate the densities.
Suppose we place a window of volume $V$ around $\mathbf{x}$ and capture $k$ samples, $k_{i}$ of which are labeled $\omega_{i}$.
Then we estimate the joint probability $p(\mathbf{x}, \omega_{i})$ as:
$ p_{n}(\mathbf{x}, \omega_{i}) = \frac{ k_{i}/n }{ V } = \frac{ k_{i} }{ nV } $
And so we use Bayes law to get the estimate for $P(\omega_{i} | \mathbf{x} )$:
$ P_{n}( \omega_{i} | \mathbf{x} ) = \frac{ p_{n}(\mathbf{x}, \omega_{i}) }{ \sum_{j=1}^{c} p_{n}(\mathbf{x}, \omega_{j} ) } = \frac{ k_{i} }{ k } $
$ P_{n}(\omega_{i} | \mathbf{x} ) = \frac{ p_{n}(\mathbf{x}, \omega_{i}) }{ \sum_{j=1}^{c} p_{n}(\mathbf{x}, \omega_{j}) } = \frac{ k_{i} }{ k } $
Thus, the probability that we observe $\omega_{i}$ given $\mathbf{x}$ is simply the fraction of randomly-observed samples within the neighborhood of $\mathbf{x}$ that are labeled $\omega_{i}$.
k-NN is a conceptually simple method: it says that samples are likely to belong to the class of other samples that are nearby.
While technically it is a density estimation method, k-NN is often used to skip straight to performing classification.
I’m sparing you some details about convergence and proof of the error bounds, because they typically follow from the discussion about convergence with Parzen Windows.
The book has the details if you’re interested.
So far, we have assumed that we knew the labels associated with our samples: $\mathcal{D}_{1}$ contains samples from $\omega_{1}$, and so on.
Obviously, this is not always (or even usually) the case.
If we just have a cloud of points, how do we decide how to best cluster and classify points?
The next class, we will discuss clustering, expectation maximization, and some methods for unsupervised classification.


Cache Consistency Options
Introduction
Consistency is a quality of shared data that is relevant for distributed caching. This page explains the distributed-cache consistency models in terms of standard distributed systems theory. Distributed caches are available when using the Terracotta Server Array, available with BigMemory Max.
Propagation of Modified Data
In general, any data cached in the heap is always consistent in that heap. For example, if one thread gets and modifies a cached element, another thread that then gets that element sees the change as long as all activity takes place in that heap.
If, however, other data tiers are involved, it is possible for the second thread to get the original element, not the changed element. If a cache.get("key").getValue().modify()
happens, after which the element is flushed to a lower tier (to BigMemory or disk, for example), then a subsequent get obtains the original element (not the changed element). To ensure that subsequent get()
operations obtain the changed element, the changed element should be put back into the cache. To guarantee this behavior without having to perform a put()
, set the cache’s copyOnRead
attribute to false.
Server-Side Consistency
Leaving aside the issue of data also held in the Ehcache nodes, let us look at the server side consistency of the Terracotta Server Array (TSA).
Server Deployment Topology
Large datasets are handled with partitions that are managed automatically using a consistent hashing algorithm. The TSA has an active server that handles all requests for that partition.
There is no dynamic resizing of clusters, so the consistent hash always resolves to the same stripe. A “stripe” or “Mirror Group” is configured in the the <tc-config> to have one active server and one or more mirror servers. The active server propagates changes to the mirror server(s). A mirror server is a hot standby, which does not service any requests unless the active server goes down, in which case a mirror server can take over the role of active server.
In the language of consistency protocols, the active and mirror are replicas - they should contain the same data.
Restating in terms of Quorum based replicated-write protocols
To use the terminology from Gifford (1979), a storage system has N storage replicas. A write is a W. A read is an R. The server-side storage system is strongly consistent if:
-
R + W > N
and
-
W > N/2
In Terracotta, there is typically one active server and one mirror server. The acknowledgement is not sent until all servers have been written to. We always read from only one replica, the Active. So R = 1, W = 2, N = 2. Substituting the terms of R + W > N, we get 1 + 2 > 2, which is clearly true. And for W > N/2 we get 2 > 2/2 => 2 > 1 which is clearly true. Therefore we are strongly consistent on the server side.
Client-Side Consistency
Data is held not only in on the server-side TSA, but also in Ehcache nodes. The client application interacts with these Ehcache nodes. Werner Vogel’s seminal “Eventually Consistent” paper presented standard terms for client-side consistency and a way of reasoning about whether that consistency can be achieved in a distributed system. Vogel’s paper in turn referenced Tannenbaum’s Distributed Systems: Principles and Paradigms (2nd Edition).
Tannenbaum was popularising research work done on Bayou, a database system. See “Distributed Systems, Principles and Paradigms” by Tannenbaum and Van Steen, page 290.
Model Components
Before explaining our consistency modes, we need to explain the standard components of the reference model, which is an abstract model of a distributed system that can be used for studying interactions.
- A storage system. The storage system consists of data stored durably in one server or multiple servers connected by a network. (In Ehcache, durability is optional and the storage system might be in memory.)
- Client Process A. This is a process that writes to and reads from the storage system.
- Client Processes B and C. These two processes are independent of Process A and write to and read from the storage system. (The “processes” can be implemented as processes or threads within the same process.) The “processes” are independent and need to communicate to share information. Client-side consistency has to do with how and when observers (in this case the processes A, B, or C) see updates made to a data object in the storage systems.
Mapping the Model to Distributed Ehcache
The model maps to Distributed Ehcache as follows:
- there is a Terracotta Server Array which is the ‘storage system’;
- there are three nodes connected to the Terracotta Server Array: Ehcache A, B and C, mapping to the processes in the standard model;
- a “write” in the standard model is a “put” or “remove” in Ehcache.
Standard Client-Side Consistency Modes
The model defines modes of consistencies where process A has made an update to a data object:
- Strong consistency. After the update completes, any subsequent access (by A, B, or C) will return the updated value.
- Weak consistency. The system does not guarantee that subsequent accesses will return the updated value.
-
Eventual consistency. This is a specific form of weak consistency. The storage system guarantees that if no new updates are made to the object, eventually all accesses will return the last updated value. If no failures occur, the maximum size of the inconsistency window can be determined based on factors such as communication delays, the load on the system, and the number of replicas involved in the replication scheme. The period between the update and the moment when it is guaranteed that any observer will always see the updated value is the
inconsistency window
.Within eventual consistency there are a number of desirable properties:
- Read-your-writes consistency means process A, after it has updated a data item, always accesses the updated value and will never see an older value. This is a special case of the causal consistency model.
- Session consistency is a practical version of Read-your-writes consistency, where a process accesses the storage system in the context of a session. As long as the session exists, the system guarantees read-your-writes consistency. If the session terminates because of a failure, a new session needs to be created and the guarantees do not overlap the sessions.
- Monotonic read consistency guarantees that if a process has seen a particular value for the object, any subsequent accesses will never return any previous values.
- Monotonic write consistency guarantees to serialize the writes by the same process. Systems that do not guarantee this level of consistency are notoriously hard to program.
Consistency Modes in Distributed Ehcache
The consistency modes in Terracotta distributed Ehcache are “strong” and “eventual”. Eventual consistency is the default mode.
Strong Consistency
In the distributed cache, strong consistency is configured as follows:
<cache name="sampleCache1"
...
/>
<terracotta consistency="strong" />
</cache>
We will walk through how a write is done and show that it is strongly consistent.
- A thread in Ehcache A performs a write.
- Before the write is done, a write lock is obtained from the Terracotta Server (storage system). The write lock is granted only after all read locks have been surrendered.
- The write is done to an in-process Transaction Buffer. Within the Java process, the write is thread-safe. Any local threads in Ehcache A will have immediate visibility of the change.
- As soon as the change is in the Transaction Buffer, which is a LinkedBlockingQueue, a notify occurs, and the Transaction Buffer initiates sending the write (update) asynchronously to the TSA (storage system).
- The Terracotta Server is generally configured with multiple replicas that constitute a Mirror Group. Within the mirror group there is an active server, and one or more mirror servers. The write is to the active server. The active server does not acknowledge the write until it has written it to each of the mirror servers in the mirror group. The active server then sends back an acknowledgement to Ehcache A, and Ehcache A then deletes the write from the Transaction Buffer.
- A read or write request from Ehcache A is immediately available because a read lock is automatically granted when a write lock has already been acquired. A read or write request in Ehcache B or C requires the acquisition of a read or write lock, respectively, which will block until step 5 has occurred. In addition, if you have a stale copy locally, it is updated first. When the lock is granted, the write is present in all replicas. Because Ehcache also maintains copies of Elements in-process in potentially each node, if Ehcache A, Ehcache B, and/or Ehcache C have a copy, they are also updated before Step 5 completes.
Note: This analysis assumes that if the nonstop
is being used, it is configured with the default of Exception, so that on a clusterOffline
event no cache operations happen locally. Nonstop allows fine-grained tradeoffs to be made in the event of a network partition, including dropping consistency.
Eventual Consistency
Distributed Ehcache can have eventual consistency in the following ways:
- Configured with
consistency="eventual"
. - Set programmatically with a bulk-loading mode, using
setNodeBulkLoadEnabled(boolean)
. - Configured with <UnlockedReadsView>, a
CacheDecorator
that can be created like a view on a cache to show the latest writes visible to the local Ehcache node without respect for any locks. - Using bulk-loading Cache methods
putAll()
,getAll()
, andremoveAll()
. Note thatputAll(Collection<Element>)
does not discriminate between new and existing elements, thus resulting in put notifications, not update notifications. These can also be used with strong consistency. If you can use them, there is no need to use bulk-load mode. See the API documentation for details.
Ehcache B and C will eventually see the change made by Ehcache A, generally with a consistency window of 5 ms (with no partitions or interruptions). If a garbage collection (GC) happens on a TSA node, or Ehcache A or B, the inconsistency window is increased by the length of the GC.
If setNodeBulkLoadEnabled(true)
is used, it prevents the TSA from updating Ehcache B and C. Instead, they are set to a 5 minute fixed time to live
(TTL). The inconsistency window thus increases to 5 minutes plus the above.
If a network partition occurs that is long enough to cause an Ehcache A to be ejected from the cluster, the only configurable option is to discard on rejoin. As soon as the rejoin occurs, Ehcache A or B gets the write. From the perspective of other threads in Ehcache A, all writes are thread-safe.
Java Memory Model Honored
In all modes, the happens-before requirement of the Java Memory Model is honored. As a result the following is true:
- A thread in Ehcache A will see any writes made by another thread. => Read your writes consistency.
- Monotonic Read Consistency in Ehcache A is true.
- Monotonic Write Consistency in Ehcache A is true.
Consistency in Web Sessions
Desirable characteristics of eventual consistency are from the point of view of Ehcache A. From the context of a web application, to enable an end user interacting with a whole application to see this behavior, use sticky sessions.
This way the user interacts with the same node (Ehcache A) for each step. If an application node fails over, a new session will be established. The time between the last write, failure, detection by the load balancer and allocation to a new application node will take longer than the 5ms+ that it takes for all Ehcache nodes in the cluster to get the write. So when the new application node is switched to, eventual consistency has occurred and no loss of consistency is observed by the user.
If you want to avoid sticky sessions, try relying on the time gap between one click or submit and the next click or submit in a “click path” that takes much longer than the 5 ms.
In an Internet context, the user is distant from the server such that the response time is at least an order of magnitude greater than the inconsistency window. Probabilistically it is therefore unlikely that a user would see inconsistency.
Other Safety Features
Ehcache offers a rich set of data safety features. In this section we look at some of the others and how they interact with the
strong
and eventual
consistency.
Compare and Swap Cache Operations
We support the following Compare and Swap (CAS) operations:
cache.replace(Element old, Element new)
cache.replace(Element)
cache.putIfAbsent(Element)
cache.removeElement(Element)
In each case the TSA will only perform the write if the old value is the same as that presented. This is guaranteed to be done atomically as required by the CAS pattern.
CAS achieves strong consistency between A, B, and C with optimistic locking rather than pessimistic locking. Optimistic locking approaches are not guaranteed to succeed. If someone else changed the Element ahead of you, the methods will return false
. You should read the new value, take that into account in your business logic, and then retry your mutation.
Note that the property org.terracotta.clusteredStore.eventual.cas.enabled
must be set to “true” in order to use atomic methods with eventual consistency.
Use Cases And Recommended Practices for Consistency and Safety
We welcome your commentary to the Ehcache forum.
Shopping Cart - optimistic inventory
Problem
A user adds items to a shopping cart. Do not decrement inventory until checkout.
Solution
Use eventual consistency.
Shopping Cart with Inventory Decrementing
Problem
A user adds items to a shopping cart. There is limited inventory and the business policy is that the first user to add the inventory to their shopping cart can buy it. If the user does not proceed to checkout, a timer will release the inventory. As a result, inventory must be decremented at the time the item is added to the shopping cart.
Solution
Use strong consistency with one of:
- explicit locking
- local transactions
- XA transactions
The key thing here is that two resources have to be updated: the shopping cart, which is only visible to one user (and has low consistency requirements), and an inventory which is transactiional in nature.
Financial Order Processing - write to cache and database
Problem
An order processing system sends a series of messages in a workflow, perhaps using Business Process Management (BPM) software. The system involves multiple servers and the next step in the processing of an order can occur on any server. Let’s say there are 5 steps in the process. To avoid continual re-reading from a database, the processing results are also written to a distributed cache. The next step could execute in a few milliseconds to minutes depending on what other orders are going through and how busy the hardware is.
Solution
Use strong consistency plus XA transactions. Because the execution step cannot be replayed once completed, and might be under the control of a BPM application, it is important that the change in state gets to the cache cluster. Synchronous writes can also be used (at a high performance cost) so that the put to the cache does not return until the data has been applied. If an executing node failed before the data was transferred, the locks would still be in place, preventing readers from reading stale data, but that will not help the next step in the process. XA transactions are needed because we want to keep the database and the cache in sync.
Immutable Data
Problem
The application uses data that is immutable. Nothing is immutable forever. The key point is that it is immutable up until the time of the next software release. Some examples are:
- application constants
- reference data - such as zip codes, postal codes, telephone area codes, names of countries
If you analyse database traffic, commonly used reference data is frequent. Reference data can only be appended or read, never updated.
Solution
In concurrent programming, immutable data never needs further concurrency protection. So we can safely use use the fastest mode: eventual consistency.
Financial Order Processing - write to cache as system of record (SOR)
Problem
An order processing system sends a series of messages in a workflow, perhaps using Business Process Management software. The system involves multiple servers and the next step in the processing of an order can occur on any server. Let’s say there are 50 steps in the process. To avoid overloading a database, the processing results at each step are only written to a distributed cache. The next step could execute in a few milliseconds to minutes depending on the volume of other orders and how busy the hardware is.
Solution
Use one of:
- strong consistency and local transactions (if changes are needed to be applied to multiple caches or entries). Because the execution step, once completed cannot be replayed, and might be under the control of a BPM, it is very important that the change in state gets to the cache cluster. Synchronous writes can also be used (at a high performance cost), so that the put to the cache does not return until the data has been applied. If an executing node failed before the data was transferred, the locks would still be in place, preventing readers from reading stale data, but that will not help the next step in the process.
- CAS operations with eventual consistency. The CAS methods will not return until the data has been applied to the server, so it is not necessary to use synchronous writes. In a 50 step process, it is likely there are key milestones. Often it is desirable to record these in a database with the non-milestone steps recorded in the cache. For these key milestones use the “Financial Order Processing - write to cache and database” pattern.
E-commerce web app with Non-sticky sessions
Here a user makes reads and writes to a web application cluster. There are n servers where n > 1. The load balancer is non-sticky,
so any of the n servers can be hit on the next HTTP operation.
When a user submits using a HTML form, either a GET or POST is done based on the form action. And if it is an AJAX app, then
requests are being done with XMLHttpRequest
and any HTTP request method can be sent. If POST (form and AJAX) or PUT (AJAX) is used,
no content is returned and a separate GET is required to refresh the view or AJAX app.
Sending a change and getting a view might happen with one request or two. If it happens with two, then the same server might respond to the second request or not. The probability that the second server will be the same as the first is 1/n. AJAX apps can further exacebate this situation. A page may make multiple requests to fill different panels. This opens up the possibility of, within a single page, having data come from multiple servers. Any lack of consistency could be glaring indeed.
Solution
Use one of:
- strong consistency
- compare-and-swap (CAS)
Other options can be added depending on what is needed for the request, for example, XA if a database plus the cache is updated.
E-commerce web app with sticky sessions
Problem
Here a user makes reads and writes to a web application cluster. The load balancer is sticky, so the same server should be hit on the next HTTP operation. There are different ways of configuring sticky sessions. The same server might be used for the length of a session, which is the standard meaning, or a browser’s IP address can permanently hash to a server. In any case, each request is guaranteed to hit the same server.
Solution
The same server is always hit. The consistency mode depends on whether only the user making the changes needs to see them applied (read your writes, monotonic reads, monotonic writes), or whether they are mutating shared-state, like inventory where write-write conflicts might occur. For mutating user-only consistency, use eventual consistency. For multi-user shared state, use strong consistency at a minimum plus further safety mechanisms depending on the type of mutation.
E-commerce Catalog
Problem
Catalogs display inventory, with product details and pricing. There might be also be an inventory status of “available” or “sold out”. Catalog changes are usually made by one user or process (for example a daily update load from a supplier) and usually do not have write-write conflicts. While the catalog is often non-sticky, admin users are typically configured sticky. There is often tolerance for the displayed catalog to lag behind the change made. Users following a click path are usually less tolerant about seeing inconsistencies.
Solution
Eventual consistency:
- The person making the catalog changes can see a consistent view by virtue of the sticky session.
- End users following a click path need a consistent view. However, the network or Internet time, plus their think time to move along the path, adds up to seconds and minutes. Eventual consistency typically propagates in the order of 2+ milliseconds, so end users are not likely to notice inconsistency.


@* * Copyright 2022 HM Revenue & Customs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *@ @import pages.StatutoryLeavePayPage @this( govukLayout: templates.GovukLayoutWrapper, formHelper: FormWithCSRF, errorSummary: components.errorSummary, inputCurrency: components.inputCurrency, h1: components.h1, button: components.button, details: components.details ) @(form: Form[_])(implicit request: Request[_], messages: Messages) @govukLayout(pageTitle = Some(title(form, "statutoryLeavePay.title")), thisPage = StatutoryLeavePayPage) { @formHelper(action = routes.StatutoryLeavePayController.onSubmit(), 'autoComplete -> "off") { @errorSummary(form.errors) @h1(messages("statutoryLeavePay.heading")) @details( summaryText = messages("statutoryLeavePay.details.title") ) {
@messages("statutoryLeavePay.details.p1")


| tree |
|
ul |
- Applied to the root ul tag to identify itself as tree widget
|
|
aria-labelledby="IDREF" |
|
- Refers to the ID Of the tree header. In the give example it refers to "Tree View"
|
| treeitem |
|
li |
- Applied to the li element of ul
|
|
tabindex="-1" |
|
- Ensures the treeitem element is focusable but is not part of tab sequence. At any
point of time only one treeitem element is included as part of tabsequence
|
|
tabindex="0" |
|
- Includes the treeitem element in the tab sequence
- Only one treeitem in the tree has tabindex="0"
- By default during the page load, the first treeitem of tree
element is included in the tab sequence
- When the user navigates through the treeitem elements, the element in focus will be
included as part of tab sequence by setting tabindex="0" and other
treeitem elements are set with tabindex="-1"
|
|
aria-expanded="false" |
|
- Applied to treeitem elements that are parent nodes i.e., they contain a
ul with the group role
- Indicates that the parent node is closed i.e., the child elements i.e., descendant elements are not
visible which is syncrhonized with CSS attribute selector
|
|
aria-expanded="true" |
|
- Applied to treeitem elements that are parent nodes i.e., they contain a
ul with the group role
- Indicates that the parent node is open i.e., the child elements(i.e., descendant elements) are
visible which is syncrhonized with CSS attribute selector
|
| group |
|
ul |
- Identifies the ul element as the container of treeitem elements
that form a branch of the tree
- Browsers use the group to compute aria-level, aria-setsize and
aria-posinet values for the nodes contained in the branch
|


Friends of Grin
The following companies, institutions, or individuals have generously donated financial resources to the Grin project under our community funding model. We're grateful for their support, and are proud to display their logos or names as supporters of Grin.
Companies & Individuals
Redouan Ahaloui
Aurel
Leonid Beder
Roy Blankman
Ivan Brightly
Guy Corem
Chance Du
Adonis Ferreira
fengqingyang
Roderik van der Graaf
PANDA
Poseidon Ho
hwph
Michalis Kargakis
Baek Kyoum Kim
Sehwan Kim (misskiwi)
Mitchell Krawiec-Thayer Ph.D. (Isthmus)
John Lee (jl2fa)
Jie Liu
Jameson Lopp
juelianshana
Chris McCann
Jack Misteli Jean-Guillaume
Bart Mol
Yan Pritzker
Hendrik Richter
Niels de Ruiter
Alex (X) Sherman
Daisuke Shosaki
Max Tannahill
Tensor Turbulence
Qi Tian
Aaron Ting
Shaishav Todi
Xiake Coin
Alexander Zaidelson
zhuroulao


the purpose of this site is to educate about non-toxic living in order to encourage readers to take steps towards living a non-toxic life. it also serves as a homebase that houses a variety of information that is beneficial to those that may be beginning the non-toxic journey. whether you're looking to learn more about non-toxic living, looking for ways to make the switch or just looking for a community, this site is for you! non-toxic living is a process, it doesn't happen overnight, so utilize these tools to develop tangible ways and timelines to work through removing toxic items from your home. take a deep breath, dive in deep and get ready to flourish!
non-toxic living is filling one's home and life with products that are free of harmful substances, including chemicals and poisons. many products used on the daily can cause harm, often unknowlingly. removing toxic products from one's home and routine and replacing them with organic, natural, chemically-free, environmentally-safe substitutes is living non-toxic.


{% block head %} {% endblock %}
E-App :: DS4A :: Team 51
Energy for all...
Home
Electricity consumption
Solar energy
Historical data
Forecasting
Wind energy
Historical data
Forecasting
Credits
Team 51
Toggle Sidebar
{% block content %} {% endblock %}


|
| uniform_real_distribution< double > | distX |
| |
| uniform_real_distribution< double > | distY |
| |
| uniform_real_distribution< double > | distZ |
| |
| UniformDistributionGenerator::UniformDistributionGenerator |
( |
| ) |
|
| UniformDistributionGenerator::~UniformDistributionGenerator |
( |
| ) |
|
|
virtual |
| vector< point > UniformDistributionGenerator::getNPoints |
( |
int |
n | ) |
|
|
virtual |
Return a vector of n
points of the distribution.
- Parameters
-
| n | Amount of output points. |
- Returns
- Vector of distribution points.
Implements DistributionGenerator.
| void UniformDistributionGenerator::initialize |
( |
int |
seed, |
|
|
double * |
boundingBox |
|
) |
| |
|
virtual |
Initializer of the generator. Execute it before any getter call is performed.
Reimplemented from DistributionGenerator.
| uniform_real_distribution<double> UniformDistributionGenerator::distX |
|
private |
Generator for X component
| uniform_real_distribution<double> UniformDistributionGenerator::distY |
|
private |
Generator for Y component
| uniform_real_distribution<double> UniformDistributionGenerator::distZ |
|
private |
Generator for Z component
The documentation for this class was generated from the following files:
- structures/domain/UniformDistributionGenerator.h
- structures/domain/UniformDistributionGenerator.cpp


Shipping specialization: a story of soundness
Rust’s impl
specialization is a major language feature that appeared
after Rust 1.0, but has yet to be stabilized, despite strong demand.
Historically, there have been three big blockers to stabilization:
The interplay between specialization rules and coherence, which I resovled in an earlier blog post.
The precise ways in which specialization employs negative reasoning, which will be resolved by incorporating ideas from Chalk into the compiler.
The soundness of specialization’s interactions with lifetimes. The RFC talks about this issue and proposes a way to address it, but it has never been implemented, and early attempts to implement it in Chalk have revealed serious problems.
I’ve been wrestling, together with nmatsakis, withoutboats and others, with these soundness issues.
Spoiler alert: we have not fully solved them yet. But we see a viable way to ship a sound, useful subset of specialization in the meantime. Feel free to jump to “A modest proposal” if you just want to hear about that.
This blog post is an attempt to write up what we’ve learned so far, with the hopes that it will clarify that thinking, and maybe open the door to you cracking the nut!
The problem
In stable Rust, it is not possible for lifetimes to influence runtime behavior. This is partly an architectural issue, and partly a design issue:
Architecture: the compiler erases lifetime information prior to monomorphization and code generation, meaning that the generated code simply has no way to depend on lifetimes. That could be changed, but we’d have to work hard to avoid code blowup by generating separate copies of code for each lifetime it was used within, assuming that the behavior didn’t change.
Design: lifetime inference generally chooses the smallest lifetime that fits the constraints at any given moment. That means that you can have a piece of data that is valid for the
'static
lifetime, yet is viewed as having a shorter lifetime. Having runtime behavior depend on these choices seems bound to result in confusion and bugs.
Unfortunately, specialization makes the story more difficult:
trait Bad1 {
fn bad1(&self);
}
impl<T> Bad1 for T {
default fn bad1(&self) {
println!("generic");
}
}
// Specialization cannot work: trans doesn't know if T: 'static
impl<T: 'static> Bad1 for T {
fn bad1(&self) {
println!("specialized");
}
}
fn main() {
"test".bad1()
}
What does this program print? Since the string literal "test"
has type
&'static str
, you might expect the second, specialized impl
to be used (and
hence to get specialized
as the output). But, as explained above, from the
perspective of trans this type will look like &'erased str
, making it
impossible to know whether the more specialized impl
can safely be used.
Here’s another, less obvious example:
trait Bad2<U> {}
impl<T, U> Bad2<U> for T {}
// Specialization cannot work: trans doesn't know if two refs have equal lifetimes
impl<'a, T, U> Bad2<&'a U> for &'a T {}
Here, the second impl
is requiring that two lifetimes are the same, and once
more for trans we can’t tell whether the impl
safely applies.
On the other hand, simply naming a lifetime that must exist, without constraining it, is fine:
trait Good {}
impl<T> Good for T {}
// Fine: specializes based on being *any* reference, regardless of lifetime
impl<'a, T> Good for &'a T {}
In addition, it’s in principle okay for lifetime constraints to show up as long as they don’t influence specialization:
trait MustBeStatic {}
impl<T: 'static> MustBeStatic for T {}
// Potentially fine: *all* impls impose the 'static requirement; the dispatch is
// happening purely based on `Clone`
impl<T: 'static + Clone> MustBeStatic for T {}
Why does this lead to unsoundness?
So far, it might seem like we can just be conservative in trans, which could lead to confusing behavior but is otherwise alright.
Sadly, it’s not, at least given the original design of specialization:
trait Bomb {
type Assoc: Default;
}
impl<T> Bomb for T {
default type Assoc = ();
}
impl Bomb for &'static str {
type Assoc = String;
}
fn build<T: Bomb>(t: T) -> T::Assoc {
T::Assoc::default()
}
fn main() {
let s: String = build("Uh oh");
drop(s) // typeck and trans disagree about the type of `s`
}
The problem here: specialization as originally designed will allow the
typechecker to conclude that T::Assoc
is String
if it knows that T
is
&'static str
. That’s because the impl for &'static str
does not use the
default
keyword when defining its associated type, meaning that no further
specialization is allowed (so the type checker knows everything there is to
know).
But trans, of course, sees &'erased str
instead, and so cannot safely use the
specialized impl
. That means that trans will make the call to build
return
()
, but the rest of the code assumed that a String
was returned.
Oops.
(Spoiler alert: the “as originally designed” bit above is a give-away of where we’re ultimately going to end up…)
Some “solutions” that don’t work
Before giving my proposed way forward, let me explain why some of the solution that are probably coming to mind don’t work out.
Can’t we just rule out “bad” specializations?
It’s very tempting to blame the specialized impl
s for Bad1
and Bad2
above,
since they clearly impose lifetime constraints. Maybe we could just make it an
error to do so.
Unfortunately, the trait system is very powerful, and you can “hide” lifetime constraints within other trait impls that don’t involve specialization. Worse still: the problem can arise from two independent crates, each of which is doing something seemingly reasonable.
////////////////////////////////////////////////////////////////////////////////
// Crate marker
////////////////////////////////////////////////////////////////////////////////
trait Marker {}
impl Marker for u32 {}
////////////////////////////////////////////////////////////////////////////////
// Crate foo
////////////////////////////////////////////////////////////////////////////////
extern crate marker;
trait Foo {
fn foo(&self);
}
impl<T> Foo for T {
default fn foo(&self) {
println!("Default impl");
}
}
impl<T: marker::Marker> Foo for T {
fn foo(&self) {
println!("Marker impl");
}
}
////////////////////////////////////////////////////////////////////////////////
// Crate bar
////////////////////////////////////////////////////////////////////////////////
extern crate marker;
pub struct Bar<T>(T);
impl<T: 'static> marker::Marker for Bar<T> {}
////////////////////////////////////////////////////////////////////////////////
// Crate client
////////////////////////////////////////////////////////////////////////////////
extern crate foo;
extern crate bar;
fn main() {
// prints: Marker impl
0u32.foo();
// prints: ???
// the relevant specialization depends on the 'static lifetime
bar::Bar("Activate the marker!").foo();
}
The problem here is that all of the crates in isolation look perfectly innocent.
The code in marker
, bar
and client
is accepted today. It’s only when these
crates are plugged together that a problem arises – you end up with a
specialization based on a 'static
lifetime. And the client
crate may not
even be aware of the existence of the marker
crate.
If we make this kind of situation a hard error, we could easily end up with a scenario in which plugging together otherwise-unrelated crates is impossible. Or where a minor version bump in one dependency could irrevocably break your code.
Can we make a knob: “lifetime-dependent” vs “specializable”?
Thinking more about the previous example, you might imagine the problem is that
the Marker
trait ends up being used in two incompatible ways:
- It’s used in a specialization, the second
Foo
impl
. - It’s used in
impl
s that constrain lifetimes (theBar
impl
).
It’s the combination of these things that gets us into trouble. And each one
arises from a different crate. So you might be tempted to add an attribute, say
#[lifetime_sensitive]
, which allows for impl
s that constrain lifetimes but
prevents use in specialization.
In other words, the Marker
trait could say, in advance, whether the Foo
impls or the Bar
impl are acceptable.
There are several downsides to this idea, but the real death-knell is that “constraining lifetimes” is a surprisingly easy thing to do. To wit:
trait Sneaky {
fn sneaky(self);
}
impl<T> Sneaky for T {
default fn sneaky(self) {
println!("generic");
}
}
impl<T> Sneaky for (T, T) {
fn sneaky(self) {
println!("specialized");
}
}
fn main() {
// what does this print?
("hello", "world").sneaky()
}
Here we have a specialized impl
that doesn’t mention any lifetimes or any
other traits; it just talks about the type (T, T)
. The problem is that it’s
asking for the two tuple components to have the same type, which means that
if a lifetime appears, it must be the same in both.
Once more, when we go to trans the main
function, we’ll be invoking sneaky
on the type (&'erased str, &'erased str)
, and we can’t tell for sure whether
the more specialized impl applies.
But saying that you can never repeat a type within a specialization would be very restrictive. And there’s always the worry that we’ve missed other sneaky ways to constrain lifetimes…
Can we make trans smarter?
At this point it becomes tempting to start blaming trans. After all, if we tracked lifetime information all the way through, wouldn’t that solve everything?
It would solve some things: it would make specialization sound. But at a high cost.
As explained at the outset, tracking information through trans would involve a massive overhaul of the compiler, and we’d have to be very smart about coalescing code with different lifetimes but identical behavior. There’s no guarantee we could do this without making the compiler significantly slower and/or creating more code bloat.
More fundamentally, though, it would lead to highly unpredictable behavior:
trait Print() {
fn print(self);
}
impl<'a, T> Print for &'a str {
fn print(self) {
println!("Arbitrary str: {}", self);
}
}
impl<T> Print for &'static str {
fn print(self) {
println!("'static str: {}", self);
}
}
fn print_str(s: &str) {
s.print()
}
fn main() {
let s = "hello, world!";
s.print();
print_str(s);
}
Does this program print 'static str: hello, world!
twice?
No! Because the call to print_str
will reborrow the string slice at a
shorter lifetime, and so trans will monomorphize it differently.
Making program behavior sensitive to the exact rules around lifetime inference and reborrowing seems extremely risky.
 Later in this post we’ll look at some more promising, clever solutions. But none of them have worked out completely, so I want to pause here and propose an incremental step forward.
First off, we add a new feature gate, assoc_specialization
, which is needed
whenever you use default type
in an impl. We then focus on stabilizing just
the core specialization
feature, i.e. without being able to specialize
associated types. That immediately means we can stop worrying about making type
checking and trans agree, since type checking will essentially no longer care
about specialization.
Many uses of specialization, including most of the original motivating examples, do not need to be able to specialize associated types.
With that out of the way, we still have work to do at the trans level. In particular, we must ensure that trans is conservative when it comes to lifetime constraints. The proposal here is twofold:
Any time a specialized impl imposes any lifetime constraints not present in the more general impl, trans uses the more general impl instead.
However, in these cases, we trigger an error-by-default lint to warn that a possibly-applicable specialization is not being used. (This needs to be a lint, not a hard error, because the relevant impls aren’t always under your crate’s control.)
Let’s revisit some of the earlier examples in this light:
// Specialization cannot work: trans doesn't know if T: 'static:
trait Bad1 {
fn bad1(&self);
}
impl<T> Bad1 for T {
default fn bad1(&self) {
println!("generic");
}
}
impl<T: 'static> Bad1 for T {
fn bad1(&self) {
println!("specialized");
}
}
fn main() {
// prints `generic`, but also generates a warning
"test".bad1()
}
For this example, trans would pick the generic implementation, but issue a
warning that a specialization might have applied. You could imagine going
further and detecting simple cases like this where a given impl will never be
used (as in the second impl of Bad1
) and issuing errors. But as explained
above, we cannot catch them all.
On the other hand, consider this case:
trait MustBeStatic {}
impl<T: 'static> MustBeStatic for T {}
impl<T: 'static + Clone> MustBeStatic for T {}
Here, both impls impose 'static
constraints, so the second impl doesn’t impose
any new lifetime constraints, and trans can choose it.
To make this work, in trans, when we query the trait system we replace each
instance of 'erased
with a distinct, fresh lifetime variable, which is a
simple way to encode that anything we deduce in the query must be valid for
all sets of unerased lifetimes. The Chalk approach will make this quite easy
to do.
Even for the cases we’re covering, though, it’s possible to do better (we’ll see more on that later). That means we might want to “improve” the behavior of trans after stabilizing the core of specialization. Fortunately, we should be able to statically detect all cases where the behavior of trans would change, and issue a different warning that the behavior will improve. That gives us leverage to use something like epochs to make trans smarter over time, while still shipping some version of specialization relatively soon.
The only alternative seems to be to continue to pursue increasingly clever solutions before shipping anything—which is a worrying approach to take when it comes to soundness. Better, in my opinion, to ship a sound 80% of the feature now, with some rough edges, and improve it over time.
Going deeper
Before I close out this post, I want to write out some of the further explorations we’ve done, and what we’ve learned.
Here’s an interesting example:
trait Special {
fn special(&self);
}
impl<T> Special for T {
default fn special(&self) {
println!("generic");
}
}
impl<T> Special for (T, T) {
fn special(&self) {
println!("specialized");
}
}
fn pair<T: Clone>(t: T) {
(t.clone(), t).special()
}
fn main() {
pair("hi");
}
Using the strategy outlined above, trans will go from (&'erased str, &'erased
str)
to (&'a str, &'b str)
and hence use the generic implementation (and
issue a lint that the more specific impl is being ignored). However, type
check could deduce that the more specialized impl always applies when invoking
special
in pair
, and you could imagine communicating that information down
to trans.
What’s going on here is that type check sees things before monomorphization, and
trans sees them afterward. In this particular case, that ends up making trans
more conservative, since it can’t tell that two appearances of 'erased
always
come from the same, single lifetime.
The story changes if we add one layer of “indirection” around trait dispatch:
trait Special {
fn special(&self);
}
impl<T> Special for T {
default fn special(&self) {
println!("generic");
}
}
impl<T> Special for (T, T) {
fn special(&self) {
println!("specialized");
}
}
fn use_special<T: Special>(t: T) {
t.special()
}
fn pair<T: Clone>(t: T) {
use_special((t.clone(), t))
}
fn main() {
pair("hi");
}
Now at type checking time, the actual use of special
occurs in a context where
we don’t know that we’ll always be using the more specialized version.
Why harp on this point? Well, for one, it’s the main issue in allowing for sound
specialization of associated types. We can see this in a variant of the Bomb
example:
trait Bomb {
type Assoc: Default;
}
impl<T> Bomb for T {
default type Assoc = ();
}
impl<T> Bomb for (T, T) {
type Assoc = String;
}
fn build<T: Bomb>(t: T) -> <(T, T) as Bomb>::Assoc {
<(T, T) as Bomb>::Assoc::default()
}
fn main() {
let s: String = build("Uh oh");
drop(s) // typeck and trans disagree about the type of `s`
}
Here, again, type check knows that the relevant uses of Bomb
all involve types
of the form (T, T)
and therefore can use the specialized version, and that
could be communicated to trans. But, once more, adding a layer of indirection
makes that much harder:
trait Bomb {
type Assoc: Default;
}
impl<T> Bomb for T {
default type Assoc = ();
}
impl<T> Bomb for (T, T) {
type Assoc = String;
}
fn indirect<T: Bomb>() -> T::Assoc {
T::Assoc::default()
}
fn build<T: Bomb>(t: T) -> <(T, T) as Bomb>::Assoc {
indirect::<(T, T)>()
}
fn main() {
let s: String = build("Uh oh");
drop(s) // typeck and trans disagree about the type of `s`
}
The problem is that type check can no longer tell trans to use the specialized
impl in the call to Assoc::default
, but it is still assuming that the
specialized impl is used externally (i.e., in the build
function).
To sum up, there are two inter-related places where type check and trans differ:
- Lifetime erasure
- Monomorphization
We can partly deal with the first of these by introducing fresh lifetime variables for each lifetime that appears in type check, just as we do for trans—basically asking for the trait system to only find answers that would apply for arbitrary lifetime choices.
The monomorphization issue, though, appears much harder to cope with. One
possible avenue is to track impl choices in a way that crosses functions, in
other words allowing the knowledge from build
that the specialized impl of
Bomb
can be used to be used when monomorphizing and generating code for
indirect
. Niko tells me that, in ancient times, the compiler used to do
something much like this—and that it was incredibly painful and complicated.
In any case, taking these further steps would appear to require substantial additional work, and it seems hard to achieve confidence in their soundness. So dropping associated type specialization for now, where it’s relatively easy to argue for soundness, seems like the right step to take (@arielb1, here’s where you prove me wrong).


{%extends 'base-inner.html' %} {% block title %} Press Release {% endblock title %} {% block content %}
Delegates may unilaterally submit Press Releases to the Press Corps and Crisis Staffers. Select the sponsoring delegate and type the release below.
Submitting press releases helps Press Corps cover your committee. Thank you!


Are you sure you want to disable job '{{jobId}}'?
Specifies what to do with active tasks associated with the job:
{{errorText()}}


pipe
Path: CARNOT/hydraulics
Purpose
To model of pipe connection between two components.
Description
For all thermal calculations see block "Pipe_basic". The only difference is
the pressure drop calculation.
In
the
pipe
the pressure drop is:
where lin and qua are fixed
parameters defined by the user.
Parameters and Dialog Box
- diameter of the pipe [m]
- length of the pipe [m]
- heat loss coefficient [W/(m2K)] (reference
is inner pipe surface)
- effective axial heat conduction [W/(mK)] ( =
A(cross-section of wall) / PI*(d2/4)*lambdaWall)
- capacity of pipe wall per length [J/(m*K)] (heat
capacity = cWall*mWall/length)
- initial temperature [°C]
- number of nodes (for numeric, a reasonable value is one
node per meter of pipe length)
- pressure drop linear in mass flow [Pa*s/kg]
- pressure drop linear in mass flow [Pa*s2/kg2]
- height between pipe inlet and pipe outlet (outlet above inlet
is positive). For simplification you may set height to zero in pump systems
when thermosyphon flow is not significant.
Characteristics
Direct Feedthrough Yes
Sample
time
Inherited
from driving block
States
corresponding
to the number of nodes
Vectorized
No


Crystal Game!
How to Play:
Objective: Each crystal will generate a random number each time it's clicked. So the objective of this game is to generate random numbers by clicking on the crystals to generate random numbers and in order to win, you must garner a total of
Points: